使用带有 DELETE 的 T-SQL EXCEPT / 优化查询

Posted

技术标签:

【中文标题】使用带有 DELETE 的 T-SQL EXCEPT / 优化查询【英文标题】:Using T-SQL EXCEPT with DELETE / Optimizing a query 【发布时间】:2017-03-31 14:39:05 【问题描述】:

以下代码从表中删除与非活动项目相关的任务记录。

delete from [Deliverables] where 
[Deliverables].[ProjectID] not in 
(
select 
[ProjectID] from [ActiveProjects]
)

我在某处读到,将NOT IN 与返回大量值的子查询一起使用并不是最有效的做法,最好使用EXCEPT 子句。

但是,当我尝试使用以下代码时,出现错误(关键字“except”附近的语法不正确。)

delete from [Deliverables]
except
select * from [Deliverables], [ActiveProjects]
where [Deliverables].[ProjectID] = [ActiveProjects].[ProjectID]

如何将EXCEPTDELETE 一起使用?如果我不能,有什么方法可以优化我的查询以更快地执行?

【问题讨论】:

【参考方案1】:

您也可以尝试not exists,脚本如下所示:

delete from [Deliverables] 
where not exists 
    (select 1 
        from [ActiveProjects]
        where [ActiveProjects].[ProjectID] = [Deliverables].[ProjectID])

如果[ActiveProjects]中有很多数据,那应该是更好的解决方案,但是它是所有数据依赖的,所以请在使用前测试效率。

【讨论】:

这个解决方案对我有用,它比使用 NOT IN 子句要快得多。谢谢! 这是一个不错的解决方案(我赞成),但并没有真正回答有关 EXISTS 部分的问题。 EXISTS 与 SELECT 语句一起使用。将它与 DELETE 一起使用的唯一方法是,如果您还按照其他解决方案中所示的方式执行 JOIN(这是我试图避免的)。另见:***.com/q/55423803/2949093【参考方案2】:

像这样尝试(通过添加 where 子句和列名等来修改您的需要)

delete from table1
  from table1 a
 inner join
      ( select your_column
          from table1
        except
        select your_column
          from table2
      ) b
    on a.your_column = b.your_column;

【讨论】:

【参考方案3】:
delete d
from [Deliverables] as d
    inner join (
        select d2.[ProjectId] from [Deliverables] as d2
        EXCEPT
        select ap.[ProjectId] from [ActiveProjects] as ap
     as todel on
        ((todel.[ProjectId] is NULL) and (d.[ProjectId] is NULL))
        or todel.[ProjectId] = d.[ProjectId]

一个微妙之处:关于 EXCEPT 的好处是它将等同于 NULL 值,而不是决定它们永远不匹配(就像“=”那样)。在您的简单示例(仅查看 id)中,这不太可能有价值,但是如果您正在比较允许空值的表的较大部分,您将不得不考虑这种尴尬的“空匹配”或错过很多行。

【讨论】:

以上是关于使用带有 DELETE 的 T-SQL EXCEPT / 优化查询的主要内容,如果未能解决你的问题,请参考以下文章

T-SQL INSTEAD OF DELETE 触发器在没有“挑衅”的情况下触发

T-SQL:带有游标的 sp_depends

使用 .NET SqlCommand 运行带有 EXECUTE AS 语句的 t-sql 存储过程

T-SQL查询2

T-SQL语法基础

存储过程