INSTEAD OF UPDATEトリガーを持つテーブルに対するUPDATEが、クラスター化インデックスの更新だけでなく、クラスター化インデックスの挿入も行うように見えるのはなぜですか?


10

非常に単純な例から始めましょう。2つのテーブルが同じスキーマで、PKでクラスター化されていますが、そのうちの1つに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

標準テーブルに対する更新のクエリプランを表示すると、予想される大量のインデックスの更新が得られます。

UPDATE Standard SET
    V = 1
    WHERE PK = '1E58B555-B073-471E-B576-4B09C8E18976'

ここに画像の説明を入力してください

ただし、トリガーを使用してテーブルに対して同様の更新を実行すると、クラスター化インデックスの更新だけでなく、クラスター化インデックスの挿入のように見えます。

UPDATE InsteadOf SET
    V = 1
    WHERE PK = '1E58B555-B073-471E-B576-4B09C8E18976'

ここに画像の説明を入力してください

どうしてこれなの?このクエリプラン(クエリ#4)の後半で予想したクラスター化インデックスの更新を確認できますが、クエリ#1でこの追加の挿入を取得するのはなぜですか?

回答:


10

INSTEAD OFトリガーは、*隠された作業テーブルに影響を受けるであろう行のコピーを格納します。これは、ご覧のクラスター化インデックス挿入です。トリガー本体はこの作業テーブル*から読み取り、トリガー内のすべてのデータ変更は「通常の」演算子(例ではクラスター化インデックス更新)を使用します。


*クエリプロセッサは、ユーザーに表示される実行プランのフォームを作成するときに、内部的に作業テーブルの名前を変更します。書き込み時にはターゲットベーステーブルに名前が変更され、読み取り時には、トリガーで見られると思われるinserted程度に名前が変更されdeletedます。

詳細については、私の記事「INSTEAD OFトリガーに関する興味深いもの」を参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.