a_s*_*hie 3 sql-server delete t-sql exists
下面是一个有效的 TSQL 语句。但我想了解 SQL Server 如何处理它。
DELETE A
FROM table1 WITH (NOLOCK)
WHERE
EXISTS
(
SELECT 1
FROM
table2 B WITH (NOLOCK)
WHERE
B.id = A.id
)
Run Code Online (Sandbox Code Playgroud)
因为子查询的输出将是一个 1 的列表。SQL Server 如何知道要删除哪些行?
Eri*_*ing 12
要了解它是如何处理的,查看查询的执行计划可能更有帮助。安装脚本在最后。
首先,让我们将查询稍微更改为应该引发错误但不会引发错误的内容。
DELETE A
FROM table1 AS A
WHERE EXISTS
(
SELECT 1/0
FROM table2 B
WHERE B.id = A.id
);
Run Code Online (Sandbox Code Playgroud)
如果你只是运行,SELECT 1/0你会得到一个除以零的错误。但是有些地方在解析查询中存在表达式,但实际上并没有被优化器投影。
您所指的“列表”从未真正出现过。标识要删除的行的所有工作都是通过exists 中的where子句完成的。
当您需要了解数据流时,从右向左阅读计划是正确的方法。从左到右是逻辑的流程。
我们有:
table1散列连接确定需要去的行,并将符合条件的书签值传递给删除操作符。在这种情况下,书签用于唯一标识行,因为没有可用于使用键的聚集索引。
使用唯一的聚集索引,可以单独使用键值来标识行。对于非唯一聚集索引,额外的唯一标识符将伴随任何重复值,尽管这对您不可见。
DROP TABLE IF EXISTS table1, table2;
CREATE TABLE dbo.table1 (id int NOT NULL);
CREATE TABLE dbo.table2 (id int NOT NULL);
INSERT
dbo.table1 WITH(TABLOCK) (id)
SELECT
x.*
FROM
(
SELECT
ROW_NUMBER() OVER(ORDER BY 1/0) AS n
FROM sys.messages AS m
) AS x;
INSERT
dbo.table2 WITH(TABLOCK) (id)
SELECT
t.*
FROM dbo.table1 AS t
WHERE id % 2 = 0;
SELECT TOP (100) t1.* FROM dbo.table1 AS t1;
SELECT TOP (100) t2.* FROM dbo.table2 AS t2;
Run Code Online (Sandbox Code Playgroud)