删除ID与另一个表不匹配的SQL行


160

我正在尝试删除mysql表中的孤立条目。

我有2张桌子,像这样:

files

| id | ....
------------
| 1  | ....
| 2  | ....
| 7  | ....
| 9  | ....

blob

| fileid | ....
------------
| 1  | ....
| 2  | ....
| 3  | ....
| 4  | ....
| 4  | ....
| 4  | ....
| 9  | ....

fileidid列可以被用来连接表在一起。

我想删除表blob中所有在表中fileid找不到的行files.id

因此,使用上面的示例将删除表中的行:3&4(s)blob


1
如果使用,请跳至第二个答案null
Pacerier

Answers:


326

使用LEFT JOIN / IS NULL:

DELETE b FROM BLOB b 
  LEFT JOIN FILES f ON f.id = b.fileid 
      WHERE f.id IS NULL

使用不存在:

DELETE FROM BLOB 
 WHERE NOT EXISTS(SELECT NULL
                    FROM FILES f
                   WHERE f.id = fileid)

使用NOT IN:

DELETE FROM BLOB
 WHERE fileid NOT IN (SELECT f.id 
                        FROM FILES f)

警告

只要有可能,就在事务中执行DELETE(假设受支持-IE:不在MyISAM上),以便在出现问题时可以使用回滚来还原更改。


12
一般来说,以上哪项最快?
Hampus Brynolf '04年

2
由于某些原因,使用左联接删除在MS SQL Server Mgmt Studio上不起作用(不确定原因;它只是抱怨左联接)。有人知道为什么吗?它使用了NOT EXISTS起作用了:)
安娜

5
仅供参考,下面是这三种方法的相对效率的有益讨论:explainextended.com/2009/09/18/...
moustachio

2
@Pacerier-“错误”有点强。为了确保人们了解,答案,如果工作fileid不可为空。同样,第三个解决方案(NOT IN)仅要求f.id非null值。大概那是主键,事实也是如此。
ToolmakerSteve

2
对于尝试使用SQLite的用户:请参阅此答案
bunkerdive

26
DELETE FROM blob 
WHERE fileid NOT IN 
       (SELECT id 
        FROM files 
        WHERE id is NOT NULL/*This line is unlikely to be needed 
                               but using NOT IN...*/
      )

什么是“ / *这行不太可能需要,但使用NOT IN ... * /”应该是什么意思?
Pacerier,2015年

1
@Pacerier- NOT IN (NULL)返回空结果集,因此需要排除NULL。但是id列无论如何都不会为空,因此“不太可能需要”
Martin Smith

哇好抓。因此,omgponies的回答是错误的!not in(null)很合逻辑,为什么不起作用?这背后的理由是什么?
Pacerier,2015年


1
@bunkerdive然后使用包含数据库名称的三个部分对象名称。
马丁·史密斯

17
DELETE FROM blob
WHERE NOT EXISTS (
    SELECT *
    FROM files
    WHERE id=blob.id
)

1
我认为这里有files.idblob.fileid。我猜您的查询将导致错误。
jww

-8
delete from table1 t1 
    WHERE not exists (select id from table2 where related_field_in_t2=t1.id) 
    AND not exists (select id from table3 where related_field_in_t3=t1.id) 
    AND not exists (select id from table4 where related_field_t4=t1.id) 
    AND not exists (select id from table5 where related_field_t5=t1.id);

3
我之所以投票,是因为:1.这不会尝试在已发布的上下文中回答问题。2.没有解释(仅代码回答在Stackoverflow上是低价值的)。3. NOT EXISTS已于9年前发布。4.您尚未推广始终使用全大写MySQL关键字的最佳做法。换句话说,这里没有什么值得保留的-这就是为什么我也投票决定删除此帖子的原因。
mickmackusa
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.