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.
Antworten
Zu viele Anzeigen?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
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.
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
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])