0

我正在使用此触发器来填充表中的CreatedDateLastUpdated列(类型datetime):

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

如何修改触发器以使它们都是准确的时间?

4

3 回答 3

2

这是导致问题的两个触发器的相互作用。

相反,如果您将两列都设置为默认getdate()并放弃您的insert触发器,它应该可以工作 -INSERT也不会导致UPDATE.

另一种方法是将INSERT触发器编写为INSTEAD OF执行 anINSERT而不是 an的触发器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

INSERTs 到触发器中的触发表中INSTEAD OF不会(谢天谢地)导致触发器被递归触发。如果ID是一IDENTITY列,那么它应该出现在上面的列列表中(它还没有生成)。

于 2013-03-19T09:40:59.513 回答
0

试试这个:

CREATE TRIGGER trCreatedDate ON [LasMTest]

FOR INSERT 

AS
Declare @CurrentDate Datetime
Set @CurrentDate=getdate()
UPDATE [LasMTest] SET [LasMTest].Created=@CurrentDate,[LasMTest].LastModified=@CurrentDate

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

GO
于 2013-03-19T09:35:52.090 回答
0

从 INSERT 进行更新时,您基本上希望避免 UPDATE 触发器。这称为嵌套触发器。一种简单的解决方案是用于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(Created)UPDATE 触发器的内部并抑制任何操作。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
于 2013-03-19T09:58:57.973 回答