204 Stimmen

Insert-Update-Trigger, wie man feststellt, ob Insert oder Update

Ich muss einen Einfüge- und Aktualisierungs-Trigger für Tabelle A schreiben, der alle Zeilen aus Tabelle B löscht, deren eine Spalte (z. B. Desc) Werte enthält, die dem Wert entsprechen, der in die Spalte der Tabelle A (z. B. Col1) eingefügt/aktualisiert wurde. Wie würde ich vorgehen, um es so zu schreiben, dass ich sowohl Aktualisierungs- als auch Einfügefälle behandeln kann. Wie würde ich feststellen, ob der Trigger für eine Aktualisierung oder eine Einfügung ausgeführt wird.

4voto

Ich habe einen kleinen Fehler in Grahams ansonsten guter Lösung gefunden:

Es sollte sein IF SPALTEN_AKTUALISIERT() < > 0 -- einfügen oder aktualisieren
anstelle von > 0 wahrscheinlich weil das oberste Bit als SIGNED integer sign bit interpretiert wird...(?). Also insgesamt:

DECLARE @action CHAR(8)  
IF COLUMNS_UPDATED() <> 0 -- delete or update?
BEGIN     
  IF EXISTS (SELECT * FROM deleted) -- updated cols + old rows means action=update       
    SET @action = 'UPDATE'     
  ELSE
    SET @action = 'INSERT' -- updated columns and nothing deleted means action=insert
END 
ELSE -- delete     
BEGIN
  SET @action = 'DELETE'
END

4voto

Graham Punkte 7089

Dies könnte ein schnellerer Weg sein:

DECLARE @action char(1)

IF COLUMNS_UPDATED() > 0 -- insert or update
BEGIN
    IF EXISTS (SELECT * FROM DELETED) -- update
        SET @action = 'U'
    ELSE
        SET @action = 'I'
    END
ELSE -- delete
    SET @action = 'D'

3voto

Chuck Bevitt Punkte 31

Ein potenzielles Problem bei den beiden angebotenen Lösungen ist, dass je nach Schreibweise eine Aktualisierungsabfrage möglicherweise null Datensätze aktualisiert und eine Einfügeabfrage möglicherweise null Datensätze einfügt. In diesen Fällen sind die Datensätze "Eingefügt" und "Gelöscht" leer. In vielen Fällen, wenn sowohl der Datensatz "Eingefügt" als auch der Datensatz "Gelöscht" leer sind, sollten Sie den Trigger einfach beenden, ohne etwas zu tun.

2voto

Alex Punkte 2098
declare @insCount int
declare @delCount int
declare @action char(1)

select @insCount = count(*) from INSERTED
select @delCount = count(*) from DELETED

    if(@insCount > 0 or @delCount > 0)--if something was actually affected, otherwise do nothing
    Begin
        if(@insCount = @delCount)
            set @action = 'U'--is update
        else if(@insCount > 0)
            set @action = 'I' --is insert
        else
            set @action = 'D' --is delete

        --do stuff here
    End

1voto

kRAZY Punkte 11

Das ist der Trick für mich:

declare @action_type int;
select @action_type = case
                       when i.id is not null and d.id is     null then 1 -- insert
                       when i.id is not null and d.id is not null then 2 -- update
                       when i.id is     null and d.id is not null then 3 -- delete
                     end
  from      inserted i
  full join deleted  d on d.id = i.id

Da nicht alle Spalten gleichzeitig aktualisiert werden können, können Sie überprüfen, ob eine bestimmte Spalte aktualisiert wird, indem Sie etwas wie folgt eingeben:

IF UPDATE([column_name])

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X