删除基于另一个表的表中的所有行


79

我似乎永远都不记得这个查询!

我想删除其ID与表2相同的表1中的所有行。

所以:

DELETE table1 t1
 WHERE t1.ID = t2.ID

我知道我可以进行WHERE ID IN(从table2中选择ID),但是如果可能的话,我想使用JOIN进行此查询。


您为什么要加入?
tster

有什么打算这个问题做:stackoverflow.com/questions/1590709/...
OMG小马

因为连接通常更快。
HLGEM,2009年

@tster也许是IDS的一个临时表需要被删除
斯蒂芬·梅萨

1
@HLGEM您是说查询优化器不够聪明,无法像执行联接一样快速地执行简单的“从X删除XY IN(从Bar中选择Foo)”。我会相信优化器胜过直觉。
tster

Answers:



87
DELETE t1 
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID;

我总是在delete语句中使用别名,因为它可以防止意外

DELETE Table1 

在运行前未能突出显示整个查询时导致。


5
主要赞成“总是使用别名”注释。很好的主意。
rosscova

35

ANSI SQL中没有解决方案可以在删除AFAIK中使用联接。

DELETE FROM Table1
WHERE Table1.id IN (SELECT Table2.id FROM Table2)

以后编辑

其他解决方案(有时执行速度更快):

DELETE FROM Table1
WHERE EXISTS( SELECT 1 FROM Table2 Where Table1.id = Table2.id)

最后,他的问题表明他想使用联接而不是IN子句。
斯蒂芬·梅萨

21

PostgreSQL的实现是:

DELETE FROM t1
USING t2
WHERE t1.id = t2.id;


3

我认为,如果您尝试这样做,可能会获得更多性能

DELETE FROM Table1
WHERE EXISTS (
  SELECT 1
  FROM Table2
  WHERE Table1.ID = Table2.ID
)

3

这将删除所有Table1符合条件的行:

DELETE Table1 
FROM Table2 
WHERE Table1.JoinColumn = Table2.JoinColumn And Table1.SomeStuff = 'SomeStuff'

2

发现此链接有用

从那里复制

通常,人们希望根据另一个表中的条件从表中删除一些记录。如何从其中一个表中删除而不删除两个表中的记录?

DELETE DeletingFromTable
     FROM DeletingFromTable INNER JOIN CriteriaTable
     ON DeletingFromTable.field_id = CriteriaTable.id
     WHERE CriteriaTable.criteria = "value";

关键是您将要删除的表的名称指定为SELECT。因此,JOIN和WHERE进行选择和限制,而DELETE进行删除。但是,您不仅限于一张桌子。如果您具有多对多关系(例如,杂志和订阅服务器,通过订阅连接),并且要删除订阅服务器,则还需要从连接模型中删除任何潜在的记录。

 DELETE subscribers, subscriptions
     FROM subscribers INNER JOIN subscriptions 
       ON subscribers.id = subscriptions.subscriber_id
     INNER JOIN magazines 
       ON subscriptions.magazine_id = magazines.id
     WHERE subscribers.name='Wes';

也可以使用LEFT JOIN和WHERE来删除带有联接的记录,以查看联接的表是否为NULL,以便您可以删除一个不匹配的表中的记录(例如,准备添加关系)。 )示例帖子。


2

由于OP不需要特定的数据库,因此最好使用符合标准的语句。MERGE在SQL标准中,仅用于在连接目标表上的内容时删除(或更新)行。

merge table1 t1
    using (
        select t2.ID
            from table2 t2
    ) as d
    on t1.ID = d.ID
    when matched then delete;

MERGE具有更严格的语义,可以防止某些可能不会引起注意的错误情况DELETE ... FROM。它强制执行match的“唯一性”:如果源中的许多行(内的语句using)与目标中的同一行匹配,则必须取消合并,并且SQL引擎必须引发错误。


这比删除-连接构造更干净
asakura89'1


0

删除基于另一个表的表记录

     Delete From Table1 a,Table2 b where a.id=b.id

    Or

      DELETE FROM Table1
    WHERE Table1.id IN (SELECT Table2.id FROM Table2)

  Or

        DELETE Table1
     FROM Table1 t1 INNER JOIN Table2 t2 ON t1.ID = t2.ID;

0

我知道这很旧,但是只是一个指向使用此ass引用的人的指针。我刚刚尝试过,如果您使用的是Oracle,则JOIN在DELETE语句中不起作用。您收到以下消息:

ORA-00933:SQL命令未正确结束。


有关如何在Oracle下使用join编写删除操作的示例,请参见另一个问题的答案
弗雷德里克

0

尽管OP不想使用'in'语句,但答复Ankur Gupta,这是我发现以一对多关系删除一个表中不存在于另一个表中的记录的最简单方法:

DELETE
FROM Table1 as t1
WHERE ID_Number NOT IN
(SELECT ID_Number FROM Table2 as t2)

对我来说,在Access 2016中像魅力一样工作。


0

我经常做以下类似的例子。(此示例来自在Linux上运行的Informix SE。)

本示例的重点是根据real_estate表中的信息删除所有房地产豁免/减排交易记录-因为减排应用程序存在错误。

在这种情况下,last_update != null意味着该帐户未关闭,并且res_exempt != 'p'该帐户不是个人财产(商业设备/家具)。

delete from trans 
where   yr = '16'
and     tran_date = '01/22/2016'
and     acct_type = 'r'
and     tran_type = 'a'
and     bill_no in
(select acct_no from real_estate where last_update is not null
 and res_exempt != 'p');

我喜欢这种方法,因为过滤条件(至少对我来说)在创建查询时更容易阅读,并且从现在开始数月后(当我查看它并想知道自己在想什么)时,就很容易理解。


0
delete
    table1
from 
    t2
where
    table1.ID=t2.ID

在mssql上工作

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.