stu*_*ith 10 sql-server clustered-index
我将从一个非常简单的例子开始:两个表,都具有相同的架构,聚集在 PK 上,但其中一个有一个INSTEAD OF UPDATE
触发器:
CREATE TABLE Standard
(
PK UNIQUEIDENTIFIER PRIMARY KEY CLUSTERED,
V INT NOT NULL
)
GO
CREATE TABLE InsteadOf
(
PK UNIQUEIDENTIFIER PRIMARY KEY CLUSTERED,
V INT NOT NULL
)
GO
INSERT Standard (PK, V) VALUES ('1E58B555-B073-471E-B576-4B09C8E18976', 0)
INSERT InsteadOf (PK, V) VALUES ('1E58B555-B073-471E-B576-4B09C8E18976', 0)
GO
CREATE TRIGGER TR_InsteadOf_Update ON InsteadOf INSTEAD OF UPDATE
AS
BEGIN
DECLARE @PK UNIQUEIDENTIFIER
DECLARE @V INT
DECLARE @cursor CURSOR
SET @cursor = CURSOR FOR SELECT PK, V FROM Inserted
OPEN @cursor
FETCH NEXT FROM @cursor INTO @PK, @V
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE InsteadOf SET
V = @V
WHERE PK = @PK
FETCH NEXT FROM @cursor INTO @PK, @V
END
CLOSE @cursor
DEALLOCATE @cursor
END
GO
Run Code Online (Sandbox Code Playgroud)
如果我查看针对标准表进行更新的查询计划,我会得到预期的聚集索引更新:
UPDATE Standard SET
V = 1
WHERE PK = '1E58B555-B073-471E-B576-4B09C8E18976'
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用触发器对表执行类似的更新,我会得到似乎是聚集索引插入以及聚集索引更新:
UPDATE InsteadOf SET
V = 1
WHERE PK = '1E58B555-B073-471E-B576-4B09C8E18976'
Run Code Online (Sandbox Code Playgroud)
为什么是这样?我可以在此查询计划(查询 #4)中看到我稍后预期的聚集索引更新,但是为什么我会在查询 #1 处获得这个额外的插入?
Pau*_*ite 10
一个INSTEAD OF
触发商店,就在一个隐藏的工作表*影响的行的副本。这是您看到的聚集索引插入。触发器主体从此工作表中读取*,触发器中的任何数据更改都使用“正常”运算符(在您的示例中为聚集索引更新)。
*查询处理器在构建执行计划的用户可见形式时在内部重命名工作表。当写它,它被重命名为目标基表,读取数据时,它被更名为inserted
或deleted
或多或少的人希望在一个触发器看到。
有关更多详细信息,请参阅我的文章有关 INSTEAD OF 触发器的有趣内容。