Perché un UPDATE su una tabella con un trigger INSTEAD OF UPDATE sembra eseguire un inserimento dell'indice cluster, nonché un aggiornamento dell'indice cluster?


10

Inizierò con un esempio molto semplice: due tabelle, entrambe con lo stesso schema, raggruppate su PK, ma una delle quali ha un INSTEAD OF UPDATEtrigger:

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

Se visualizzo il piano di query per un aggiornamento rispetto alla tabella standard, ottengo l'aggiornamento previsto dell'indice in cluster:

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

inserisci qui la descrizione dell'immagine

Tuttavia, se eseguo un aggiornamento simile sulla tabella con il trigger, ottengo quello che sembra essere un inserto di indice cluster, nonché l'aggiornamento dell'indice di cluster:

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

inserisci qui la descrizione dell'immagine

Perchè è questo? Posso vedere l'aggiornamento dell'indice cluster che mi aspettavo più avanti in questo piano di query (query n. 4), ma perché ottengo questo inserto aggiuntivo nella query n. 1?

Risposte:


10

Un INSTEAD OFtrigger memorizza una copia delle righe che verrebbero interessate in una tabella di lavoro nascosta *. Questo è l'inserto dell'indice cluster che vedi. Il corpo del trigger legge da questa tabella di lavoro * e qualsiasi modifica dei dati nel trigger utilizza l'operatore "normale" (Aggiornamento indice cluster nell'esempio).


* Il Query Processor rinomina internamente la tabella di lavoro durante la costruzione del modulo visibile dall'utente del piano di esecuzione. Durante la scrittura, viene rinominato nella tabella di base di destinazione, durante la lettura, viene rinominato come insertedo deletedpiù o meno come le persone si aspetterebbero di vedere in un trigger.

Per maggiori dettagli, vedi il mio articolo Cose interessanti sui trigger INSTEAD OF .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.