我正在使用此触发器在表格中填写CreatedDate
和LastUpdated
列(类型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
如何修改触发器以确保它们都是准确的时间?
答案 0 :(得分: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
进入INSTEAD OF
触发器中的触发表时(谢天谢地)会导致触发器被递归触发。如果ID
是IDENTITY
列,则它应显示在上面的列列表中(尚未生成)。
答案 1 :(得分: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
答案 2 :(得分:0)
从INSERT执行更新时,您基本上希望避免使用UPDATE触发器。这称为Nested Triggers。一个简单的解决方案是使用CONTEXT_INFO()
与已经在INSERT触发器中的嵌套UPDATE触发器代码进行通信,因此它会抑制自身:
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