2010-01-05 4 views
9

Ho scritto un trigger che deve eseguire un lavoro diverso su una tabella in base a quali colonne in una riga vengono effettivamente aggiornate. Ho compiuto questo utilizzandoIl trigger TSql deve essere attivato solo sulle colonne i cui valori sono stati modificati

IF UPDATE(column-name) 

Quella parte funziona bene. Risulta, tuttavia, che ci sono altre parti del codice che aggiornano le righe impostando ogni singolo valore indipendentemente dal fatto che il valore sia effettivamente cambiato e questo fa innescare il trigger per le parti che sono state "aggiornate" ma i cui valori in realtà non cambiano affatto.

Poiché la modifica del codice che causa questo non è probabilmente un'opzione, esiste un modo più semplice per evitare che questo debba essere confrontato tra le tabelle INSERTED e DELETED (nel qual caso gli UPDATE IF non hanno significato)?

risposta

14
IF EXISTS (SELECT * 
      FROM 
      INSERTED I JOIN DELETED D ON I.Key = D.Key 
      WHERE 
      I.Col <> D.Col) 
... 

o utilizzare una variabile di tabella per memorizzare nella cache evitare così l'uso ripetuto di I e D.

SELECT 
    CASE WHEN I.Col1 <> D.Col1 THEN 1 ELSE 0 END AS Col1Diff, 
    CASE WHEN I.Col2 <> D.Col2 THEN 1 ELSE 0 END AS Col2Diff, 
    ... 
FROM 
    INSERTED I JOIN DELETED D ON I.Key = D.Key 

o combinare idee per testare tutte le modifiche su fronte e uscire dal grilletto

2

Non che io sappia. INSERTED e DELETED ci sono per un motivo, e il confronto tra di loro sembra l'opzione migliore per me.

IF UPDATE() indica solo se è stato effettuato un tentativo di inserimento o aggiornamento e non riflette nemmeno se il tentativo è riuscito o meno.

4

La colonna è stata aggiornata. Che il vecchio valore e il nuovo valore fossero gli stessi è solo un dettaglio. Penso che la tua unica soluzione sia quella di confrontare i valori tra pseudo-tabelle inserite e cancellate.

7

Come altri hanno già detto, è necessario utilizzare le tabelle INSERTED e DELETED.

Ecco quello che ho fatto, invece di:

IF UPDATE(col1) OR UPDATE(col2)) 
UPDATE table1 
SET col3 = 1 
FROM INSERTED 
WHERE table1.Id = INSERTED.Id 

ho fatto:

IF UPDATE(col1) OR UPDATE(col2)) 
UPDATE table1 
SET col3 = 1 
FROM 
    (SELECT Id, col1, col2 FROM INSERTED 
    EXCEPT 
    SELECT Id, col1, col2 FROM DELETED) AS ALTERED 
WHERE table1.Id = ALTERED.Id 

Utilizzando EXCEPT seleziona le righe distinte in cui le colonne che mi interessano non esistono nella cancellato (o dati originali) tabella (significa che il valore di quelle colonne è cambiato). Non so se questa è la migliore risposta, ma sembra funzionare.