4

好的,我相信这个问题并不清楚。在这里,我以其他方式重写了这个。

假设我创建了两个表,

  • table1(c1 int PRIMARY KEY)

  • table2(table1c11 int)

和之间有关系table1table2table1.c1=table2.table1c11

table1并且,我在and中执行以下语句table2

insert into table1(c1)
values('a'),('b'),('c'),('d'),('e')

insert into table2(table1c11)
values('a'),('a'),('b'),('d')

现在我想要实现的是,一旦我更新了相应数据中c1的值,就会自动更改。为此,我需要在和关系中创建约束并应用.table1table2table1table2CASCADE UPDATE

table1所以,后来我在ie中应用了一个新的 SQL 更新语句

Update table1 set c1=c1+'updated'

然后中的数据table2也会发生变化,但是如果我想通过 实现相同的功能INSTEAD OF UPDATE TRIGGER,那么我需要编写而不是更新触发器,并且在其中,我需要使用两个魔术表INSERTEDDELETED.

但要点是,在这种情况下,我只有一列存在table1并且我正在更新同一列,所以我如何映射插入和删除的行。如果我使用 CASCADing,SQL Server 也会做同样的事情。

那么问题来了,如果表中的主键数据发生变化,SQL Server 如何处理批量更新。

4

1 回答 1

12

那么问题来了,如果表中的主键数据发生变化,SQL Server 如何处理批量更新。

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

创建表:

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.

更新1:

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

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

更新时级联超过一行的更新查询计划

顶部分支中的Eager SpoolT1 (更新)将旧T1ID的和新的计算保存T1ID (Expr1013)到较低分支使用的临时表(更新T2)。较低分支中的哈希匹配正在将 Table Spool 与T2旧的T1ID. 从哈希匹配到更新的输出来自T2聚集T2ID索引扫描和从表假脱机T2计算的新值。T1ID (Expr1013)

更新 2:

如果您需要cascade update用 a替换,instead of trigger您需要有一种方法来连接触发器中的inserteddeleted表。这可以通过 中的代理键来完成T1

表:

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

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

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

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小提琴

于 2013-02-25T10:52:18.183 回答