首页 > 解决方案 > 使用 CTE 批量删除行时如何设置更改跟踪上下文?

问题描述

我正在使用 SQL Server 2014 并希望为某些删除 SQL 设置更改跟踪上下文。DELETE SQL 使用 CTE 小批量删除行以避免锁升级:

WITH cte_rows_to_delete (id) AS   
(
     SELECT TOP 100 id 
     FROM TableA
)
DELETE FROM cte_rows_to_delete;

我可以在没有 CTE 的情况下为 DELETE 设置更改跟踪上下文:

DECLARE @dc varbinary(128) = CONVERT(VARBINARY(128), N'UseCaseA');
WITH CHANGE_TRACKING_CONTEXT (@dc) DELETE FROM TableA

但是当我把它们放在一起时,

DECLARE @dc varbinary(128) = CONVERT(VARBINARY(128), N'UseCaseA');

WITH CHANGE_TRACKING_CONTEXT (@dc) 
WITH cte_rows_to_delete (id) AS   
(
     SELECT TOP 100 id 
     FROM TableA
)
DELETE FROM cte_rows_to_delete;

我有一个错误

关键字“with”附近的语法不正确。如果此语句是公用表表达式、xmlnamespaces 子句或更改跟踪上下文子句,则前面的语句必须以分号结束。

如果我;在 CTE 前面添加一个,SQL Server 只会抱怨

';' 附近的语法不正确

我的问题是:SQL Server CTE 可以与更改跟踪上下文子句一起使用吗?我用谷歌搜索,但找不到任何有明确答案的文件。

谢谢

詹姆士

标签: sql-server

解决方案


令人费解的是,这种语法没有记录在它适用的语句中!WITH CHANGE_TRACKING_CONTEXT有自己的主题,但这并不能解释它应该如何集成到所有语句中。

根据我的实验,您使用它的方式似乎与在单个语句中声明多个 CTE 的方式大致相同:

WITH 
    CHANGE_TRACKING_CONTEXT (@dc),
    cte_rows_to_delete (id) as ( SELECT TOP 100 id from TableA) 
DELETE FROM cte_rows_to_delete;

至少,这种语法在 SQL Server 2017 中对我来说没有错误;我还没有针对启用了更改跟踪的实际数据库对其进行测试。

值得注意的是,WITH子句的顺序不是自由的:WITH CHANGE_TRACKING_CONTEXT必须首先出现,然后是任何XMLNAMESPACES声明,然后是任何 CTE。如果还有更多WITH我不熟悉的 s,它们可能也有固定的顺序。


推荐阅读