且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

级联更新/删除在SQL Server内部如何工作?

更新时间:2021-12-04 23:16:20


因此,问题出在
表中主键数据更改的情况下,SQL Server如何处理批量更新。

So, the question arises how SQL Server handles batch update in case of the primary key data changes in the table.

SQL Server为更新两个表的更新语句建立查询计划。

SQL Server builds a query plan for the update statement that update both tables.

创建表:

create table T1
(
  T1ID int primary key
);

create table T2
(
  T2ID int primary key, 
  T1ID int references T1(T1ID) on update cascade
)

添加一些数据:

insert into T1 values(1), (2)
insert into T2 values(1, 1), (2, 1), (3, 2)

更新 T1 的主键:

update T1
set T1.T1ID = 3
where T1.T1ID = 1

更新查询计划如下:

该计划有两个聚集索引更新步骤,一个用于 T1 和一个 T2

The plan has two Clustered Index Update steps, one for T1 and one for T2.

更新1:

当更新多个主键值时,SQL Server如何跟踪要更新的行?

How does SQL Server keep track of the rows to update when more than one primary key value is updated?

update T1
set T1.T1ID = T1.T1ID + 100

Easer假脱机在顶部分支( T1 的更新)中保存了旧的 T1ID 和新计算出的 T1ID(Expr1013)到下级分支使用的临时表中(更新 T2 )。下部分支中的哈希匹配将表假脱机与旧的 T1ID 上的 T2 相连。哈希匹配到 T2 更新的输出是 T2ID 来自的聚集索引扫描T2 和表假脱机中新计算出的 T1ID(Expr1013)

The Eager Spool in the top branch (update of T1) saves the old T1ID and the new calculated T1ID (Expr1013) to a temporary table that is used by the lower branch (update of T2). The Hash Match in the lower branch is joining the Table Spool with T2 on the old T1ID. Output from the Hash Match to the update of T2 is T2ID from the Clustered Index Scan of T2 and the new calculated T1ID (Expr1013) from the Table Spool.

更新2:

如果您需要将级联更新替换为而不是触发器,您需要有一种方法来加入已插入已删除触发器中的表。可以使用 T1 中的代理键来完成。

If you need to replace the cascade update with a instead of trigger you need to have a way to join the inserted and deleted tables in the trigger. That can be done with a surrogate key in T1.

表:

create table T1
(
  T1ID int primary key,
  ID int identity unique
);

create table T2
(
  T2ID int primary key, 
  T1ID int references T1(T1ID)
);

触发器可能看起来像这样。

The trigger could look like this.

create trigger tr_T1 on T1 instead of update as

insert into T1(T1ID)
select T1ID
from inserted;

update T2
set T1ID = I.T1ID
from inserted as I
  inner join deleted as D
    on I.ID = D.ID
where D.T1ID = T2.T1ID;

delete from T1
where T1ID in (
              select T1ID
              from deleted
              );

SQL小提琴