2010-07-25 107 views
2

我有以下表格:如何將更新的記錄移動到歷史記錄表中?

CREATE TABLE FE_USER 
(
    userid int identity (321,4) CONSTRAINT userid_pk PRIMARY KEY, 
    username varchar(40) 
); 

其對應的歷史表是

CREATE TABLE FE_USER_HIST 
(
    userid int, 
    username varchar(40), 
    v_action varchar(50) 
); 

每天上FE_USER表發生了插入或更新的時間,我需要輸入 這個新插入的記錄或更新記錄到歷史記錄表中。

我該如何在t-sql中編寫觸發器?

這裏是我的pseducode,但我得到了很多的錯誤:

CREATE OR REPLACE TRIGGER user_to_hist 
    AFTER UPDATE OR DELETE 
    ON FE_USER 
    FOR EACH ROW 
    DECLARE 
     v_action varchar(50); 
    BEGIN 
     v_action := CASE WHEN UPDATING THEN 'UPDATE' ELSE 'DELETE' END; 
     INSERT INTO FE_USER_HIS(userid, username, v_action) 
     SELECT :OLD.userid, :OLD.username, v_action 
     FROM .......; 
END; 

回答

5

SQL Server不支持CREATE OR REPLACE不幸。您需要使用CREATEALTER,這取決於您正在執行的操作。

另外它沒有行級觸發器。所有受影響的行都可以在僞表中使用,稱爲INSERTEDDELETED

最簡單的方法可能是2個單獨的觸發器。

對於插入

CREATE TRIGGER dbo.tr_i_FE_USER 
    ON dbo.FE_USER 
    AFTER INSERT 
AS 
BEGIN 
    SET NOCOUNT ON; 
INSERT INTO FE_USER_HIST 
SELECT userid,username, 'inserted' AS v_action 
FROM INSERTED 

END 

而對於更新

CREATE TRIGGER dbo.tr_u_FE_USER 
    ON dbo.FE_USER 
    AFTER UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON; 
INSERT INTO FE_USER_HIST 
SELECT userid,username, 'updated' AS v_action 
FROM INSERTED /*If you wanted the previous value instead 
       you could use FROM DELETED */ 

END 

只是跟進我的評論中提到的方法

CREATE TRIGGER dbo.tr_iud_FE_USER 
    ON dbo.FE_USER 
    AFTER INSERT, UPDATE, DELETE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    INSERT INTO FE_USER_HIST 
    SELECT 
    ISNULL(i.UserId,d.UserId) AS UserId, 

    CASE WHEN i.UserId IS NULL THEN d.UserName 
     ELSE i.UserName 
    END AS UserName, 

    CASE WHEN i.UserId IS NULL THEN 'deleted' 
     WHEN d.UserId IS NULL THEN 'inserted' 
     ELSE 'updated' 
    END AS v_action 
    from INSERTED i FULL OUTER JOIN DELETED d 
    ON i.UserId = d.USerId 
END 
+0

甚至是否有一個觸發的方式來確定所採取的行動(即刪除或更新)?我試圖想出一個單一的觸發器,想不到一個辦法。 – LittleBobbyTables 2010-07-26 00:10:26

+0

@LittleBobby - 你可以通過主鍵將完整的外連接插入DELETED,以確定該行是剛被刪除,剛插入還是兩者(更新) – 2010-07-26 00:14:19

+0

...雖然我猜如果PK本身更新了2個方法會產生不同的結果。 – 2010-07-26 01:00:27

2

如果你想捕獲所有三個動作我'd使用2個觸發器而不是一個:

CREATE TRIGGER user_to_historyA ON FE_USER 
AFTER INSERT, UPDATE 
AS 
DECLARE @action varchar(50) 
    SET @action = CASE WHEN UPDATE(username) THEN 'UPDATE' ELSE 'INSERT' END 

    INSERT INTO FE_USER_HIS(userid, username, v_action) 
    SELECT userid, username, @action 
    FROM inserted 

GO 


CREATE TRIGGER user_to_historyB ON FE_USER 
AFTER DELETE 
AS 
    INSERT INTO FE_USER_HIS(userid, username, v_action) 
    SELECT userid, username, 'DELETE' 
    FROM deleted 

GO 

EDIT(每馬丁的正確的關於使用無用UPDATE()函數和註釋合併成1個觸發)

ALTER TRIGGER user_to_history ON FE_USER 
    AFTER INSERT, UPDATE, DELETE 
    AS 
    DECLARE @action varchar(50) 
     IF EXISTS(SELECT username FROM inserted) 
     BEGIN 
      SET @action = CASE WHEN EXISTS(SELECT username FROM deleted) THEN 'UPDATE' ELSE 'INSERT' END 

      INSERT INTO FE_USER_HIS(userid, username, v_action) 
      SELECT userid, username, @action 
      FROM inserted 
     END 
     ELSE 
      INSERT INTO FE_USER_HIS(userid, username, v_action) 
      SELECT userid, username, 'DELETE' 
      FROM deleted 
    GO 
+0

不錯的主意,但我認爲'更新(用戶名)'將是真正的'INSERT'以及http://msdn.microsoft.com/en-us/library/ms187326.aspx。你可以看到'DELETED'僞表雖然是空的。 (即使對於SQL2008中的合併,插入和更新觸發器也會作爲單獨的操作被觸發,所以這也應該在SQL2008中起作用。) – 2010-07-26 00:20:18

+0

謝謝.......... – 2010-07-26 02:48:03

相關問題