2013-03-19 54 views
0

我才能在CreatedDateLastUpdated欄填寫表格(類型datetime的)使用該觸發器:SQL Server 2008中創建/最後更新的觸發問題

CREATE TRIGGER trCreatedDate ON [LasMTest] 
FOR INSERT 
AS 
    UPDATE [LasMTest] 
    SET [LasMTest].Created = getdate(), 
     [LasMTest].LastModified = getdate() 
    FROM [LasMTest] 
    INNER JOIN Inserted ON [LasMTest].[ID] = Inserted.[ID] 
GO 

當我檢查表中,日期只有幾分之一秒的時間。

Created LastModified ID 
2013-03-19 09:24:32.920 2013-03-19 09:24:32.930 4 
2013-03-19 09:26:39.890 2013-03-19 09:26:39.900 5 

如何修改觸發器,使它們都是準確的時間?

回答

2

這是造成問題的觸發器的相互作用。

相反,如果你兩列設置爲默認getdate()溝您insert觸發器,它應該工作 - INSERT不會也引起UPDATE

另一種方法是編寫你的INSERT觸發爲INSTEAD OF觸發器執行INSERT而不是UPDATE(因此,也避免了UPDATE觸發器觸發)。


如果你想將它寫爲INSTEAD OF觸發,這將是這樣的:

CREATE TRIGGER trCreatedDate ON [LasMTest] 
INSTEAD OF INSERT 
AS 
    INSERT INTO LasMTest (/* Column List */,Created,LastModified) 
    SELECT /* Column List */,getdate(),getdate() from inserted 
GO 

INSERT s轉換觸發表中的INSTEAD OF觸發不(謝天謝地)引起觸發器被遞歸地觸發。如果IDIDENTITY列,那麼它應該出現在上面的列表中(尚未生成)。

+0

INSTEAD OF的語法是什麼? – 2013-03-19 09:43:21

+0

創建並刪除插入觸發器的默認約束工作得很好。謝謝 – 2013-03-19 10:04:13

0

試試這個:

CREATE TRIGGER trCreatedDate ON [LasMTest] 

FOR INSERT 

AS 
Declare @CurrentDate Datetime 
Set @CurrentDate=getdate() 
UPDATE [LasMTest] SET [LasMTest][email protected],[LasMTest][email protected] 

FROM [LasMTest] INNER JOIN Inserted ON [LasMTest].[ID]= Inserted.[ID] 

GO 
+0

我都試過,太多,完全不是那麼回事,可能是因爲我有另一個觸發更新,我認爲是差異的原因。'CREATE TRIGGER trLastModifiedDate ON [LasMTest] FOR UPDATE AS UPDATE [LasMTest] SET [LasMTest] .LastModified = GETDATE() FROM [LasMTest] INNER JOIN插在[LasMTest]。[ID] =插入的。[ID]'基本上它似乎實際上觸發了當我做INSERT時,我希望它只在行被UPDATE時觸發,而不是創建,如何改變它? – 2013-03-19 09:37:30

0

你基本上想避免執行INSERT更新時的UPDATE觸發器。這叫做Nested Triggers。一個簡單的解決方案是使用CONTEXT_INFO()傳達給嵌套的UPDATE觸發器代碼,你已經是一個INSERT觸發器,因此抑制了自身:

CREATE TRIGGER trCreatedDate ON [LasMTest] 
FOR INSERT 
AS 
    SET CONTEXT_INFO 0xDEADBEEF; 
    UPDATE [LasMTest] 
    SET [LasMTest].Created = getdate(), 
     [LasMTest].LastModified = getdate() 
    FROM [LasMTest] 
    INNER JOIN Inserted ON [LasMTest].[ID] = Inserted.[ID]; 
    SET CONTEXT_INFO NULL; 
GO 

CREATE TRIGGER trModifiedDate ON [LasMTest] 
FOR UPDATE 
AS 
    DECLARE @context varbinary(128); 
    SET @context = CONTEXT_INFO(); 
    IF @context is NULL 
    BEGIN 
     UPDATE [LasMTest] 
      SET [LasMTest].LastModified = getdate() 
     FROM [LasMTest] 
     INNER JOIN Inserted ON [LasMTest].[ID] = Inserted.[ID]; 
    END 
GO 

然而這樣的做法是脆弱的。異常可以設置context_info並禁止會話中的所有後續UPDATE觸發器。這需要添加TRY/CATCH塊。而且你總是冒險使用CONTEXT_INFO自己的目的和破壞你的計劃。

另一種解決方案是使UPDATE觸發器更加智能。它可以檢查UPDATE觸發器中的UPDATE(Created),並在Created列被修改時取消任何操作。這是通過約定,因爲你知道那個更新Created列的唯一地方是INSERT觸發器:

CREATE TRIGGER trModifiedDate ON [LasMTest] 
FOR UPDATE 
AS 
    IF NOT UPDATE(Created) 
    BEGIN 
     UPDATE [LasMTest] 
      SET [LasMTest].LastModified = getdate() 
     FROM [LasMTest] 
     INNER JOIN Inserted ON [LasMTest].[ID] = Inserted.[ID]; 
    END 
GO