Почему UPDATE для таблицы с триггером INSTEAD OF UPDATE, по-видимому, выполняет вставку кластерного индекса, а также обновление кластерного индекса?


10

Я начну с очень простого примера: две таблицы, обе с одинаковой схемой, кластеризованные на ПК, но одна из которых имеет 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

An INSTEAD OFтриггер хранит копию строки , которые будут затронуты в скрытой работе таблица *. Это вкладка кластерного индекса, которую вы видите. Тело триггера считывает из этой рабочей таблицы *, и любые изменения данных в триггере используют оператор 'normal' (обновление Clustered Index Update в вашем примере).


* Обработчик запросов внутренне переименовывает рабочую таблицу при построении видимой пользователем формы плана выполнения. При записи в него он переименовывается в целевую базовую таблицу, при чтении он переименовывается как insertedили deletedболее или менее так, как люди ожидают увидеть в триггере.

Для более подробной информации, смотрите мою статью Интересные вещи о триггерах INSTEAD OF .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.