2010-12-08 15 views
8

Wenn ein Benutzer Tabelle HelloWorlds ändert, dann möchte ich 'Aktion, die sie getan haben, Zeit, die sie taten, und eine Kopie der ursprünglichen Zeile einfügen in HelloWorldsHistory.So kopieren Sie eine eingefügte, aktualisierte, gelöschte Zeile in einem SQL Server-Trigger

Ich würde lieber eine separate Trigger für Einfügen, Aktualisieren und Löschen von Aktionen aufgrund der Spaltenlängen vermeiden.

Ich habe dies versucht:

create trigger [HelloWorlds_After_IUD] on [HelloWorlds] 
FOR insert, update, delete 
as 
if @@rowcount = 0 
return 
if exists (select 1 from inserted) and not exists (select 1 from deleted) 
begin 
insert into HelloWorldHistory (hwh_action, ..long column list..) 
select 'INSERT', helloWorld.id, helloWorld.text ... and more from inserted 
end 
else 
    if exists (select 1 from inserted) and exists (select 1 from deleted) 
    begin 
insert into HelloWorldHistory (hwh_action, ..long column list..) 
select 'UPDATE', helloWorld.id, helloWorld.text ... and more from deleted 
    end 
    else 
    begin 
insert into HelloWorldHistory (hwh_action, ..long column list..) 
select 'DELETE', helloWorld.id, helloWorld.text ... and more from deleted 
    end 
end 

ich nie ein Einsatz erscheinen gesehen habe, aber ich habe gesehen Updates. Ich werde 3 separate Trigger versuchen, obwohl die Pflege der Spaltenlisten nicht Spaß machen wird.

+0

Verwenden Sie nicht DELETED als Datenquelle für UPDATEs, Sie werden nur den vorherigen Wert protokollieren, der bereits aufgezeichnet wurde. Ihre Protokollzeile wird vom Typ "Update" sein, aber die Daten könnten von einer Einfügung stammen. Sehen Sie mich in meiner Antwort kommentieren. –

Antwort

19

versuchen, etwas wie folgt aus:

CREATE TRIGGER YourTrigger ON YourTable 
    AFTER INSERT,UPDATE,DELETE 
AS 

DECLARE @HistoryType char(1) --"I"=insert, "U"=update, "D"=delete 

SET @HistoryType=NULL 

IF EXISTS (SELECT * FROM INSERTED) 
BEGIN 
    IF EXISTS (SELECT * FROM DELETED) 
    BEGIN 
     --UPDATE 
     SET @HistoryType='U' 
    END 
    ELSE 
    BEGIN 
     --INSERT 
     SET @HistoryType='I' 
    END 
    --handle insert or update data 
    INSERT INTO YourLog 
      (ActionType,ActionDate,.....) 
     SELECT 
      @HistoryType,GETDATE(),..... 
      FROM INSERTED 

END 
ELSE IF EXISTS(SELECT * FROM DELETED) 
BEGIN 
    --DELETE 
    SET @HistoryType='D' 

    --handle delete data, insert into both the history and the log tables 
    INSERT INTO YourLog 
      (ActionType,ActionDate,.....) 
     SELECT 
      @HistoryType,GETDATE(),..... 
      FROM DELETED 

END 
--ELSE 
--BEGIN 
-- both INSERTED and DELETED are empty, no rows affected 
--END 
+0

funktioniert gut. Da ich mich in den letzten paar Jahren in Oracle befand, fühlte ich mich aufgrund meiner Nähe viel besser darin, meine verstaubten MS SQL-Kenntnisse zu vertiefen. – DefyGravity

+0

Meine Endlösung wird diese "Architektur" sein, bei der die pk-Spalten von bob zwischen der Quelltabelle und den temporären Transaktions-Triggertabellen überprüft werden. Außerdem werde ich die 'UPDATE' Daten von der gelöschten Tabelle ziehen, im Gegensatz zu eingefügt. – DefyGravity

+4

Ich würde dringend empfehlen, dass Sie das UPDATE aus der INSERTED-Tabelle protokollieren. Hier ist ein Beispiel: Zeilendaten einfügen = AAA (INSERTED = AAA wird protokolliert), gleiche Zeile auf BBB aktualisieren (INSERTED = BBB, DELETED = AAA, ich sage send BBB zum Protokollieren und nicht AAA, das wurde bereits aufgezeichnet). Außerdem sind bei Verwendung der "IF EXISTS" alle "Schlüsselprüfungen" nicht notwendig und nur ein Overhead. Ein Trigger kann nur für jeweils einen Befehl ausgelöst werden, einen INSERT oder einen UPDATE oder einen DELETE. Es ist also nicht erforderlich, die Schlüssel zu vergleichen, um den Vorgang zu bestimmen. Sie werden niemals UPDATE-Daten mit INSERT-Daten innerhalb eines Triggers mischen. –

6

Sie benötigen (Spiel) assoziieren die Zeilen in den Spalten eingefügt und gelöscht. So etwas sollte besser funktionieren.

create trigger [HelloWorlds_After_IUD] on [HelloWorlds] 
FOR insert, update, delete 
as 

insert into HeloWorldsHistory 
select 'INSERT', helloWorld.id, helloWorld.text ... and more 
from inserted 
where myKeyColumn not in (select myKeyColumn from deleted) 

insert into HeloWorldsHistory 
select 'DELETE', helloWorld.id, helloWorld.text ... and more 
from deleted 
where myKeyColumn not in (select myKeyColumn from inserted) 

insert into HeloWorldsHistory 
select 'UPDATE', helloWorld.id, helloWorld.text ... and more 
from inserted 
where myKeyColumn in (select myKeyColumn from deleted) 
+0

Ich werde definitiv auf dem PK passen! Danke für diesen Fang! – DefyGravity

+1

siehe KM's Kommentar zu PK in dieser Situation – DefyGravity

Verwandte Themen