我正在尝试为表设置触发器以更新列“持续时间”,该列是行上开始日期和结束日期之间的持续时间。但是,每当我插入/更新列时,触发器都不起作用,因为SCOPE_INDENTITY()保持返回null。我该如何解决这个问题?
ALTER TRIGGER [dbo].[CalcDuration]
ON [dbo].[Event]
AFTER INSERT, UPDATE, DELETE
AS
DECLARE @STARTED datetime
DECLARE @FINISHED datetime
DECLARE @ID int
SELECT @ID = SCOPE_IDENTITY()
SELECT @STARTED = [Date & Time Started] FROM dbo.Event WHERE [Event ID] = @ID
SELECT @FINISHED = [Date & Time Finished] FROM dbo.Event WHERE [Event ID] = @ID
UPDATE dbo.Event
SET Duration = DATEDIFF ( hour, @STARTED, @FINISHED )
WHERE [Event ID] = @ID
答案 0 :(得分:1)
如果您坚持使用after
触发器(注意:不需要AFTER DELETE),您可以
CREATE TRIGGER ai_event
ON event AFTER INSERT,UPDATE
as
BEGIN
UPDATE event
SET Duration = DATEDIFF(hour, i.[Date & Time Started],i.[Date & Time Finished])
from event e
INNER JOIN INSERTED i ON (i.id = e.id)
END;
但是,在这种情况下,将Duration
作为计算[持久]列似乎是更好的选择......
ALTER TABLE event ADD Duration2 AS DATEDIFF(hour, [Date & Time Started],
[Date & Time Finished]) PERSISTED;
答案 1 :(得分:1)
SCOPE_INDENTITY()
仅返回当前作用域中最后插入的标识值,因此如果在触发器中使用它,它只会在触发器中执行插入操作后返回值 - 这不是这里的情况,因此返回NULL
我想您正在尝试获取插入/更新值的ID,在这种情况下可以使用表INSERTED
。
接下来,假设您的触发器仅在单行上工作(通常不是这种情况),您犯了一个大错误,因为UPDATE和INSERT可以在多行上工作。 INSERTED
表幸运地包含插入/更新的所有行。
所以你的触发器应该是这样的:
UPDATE e
SET e.Duration = DATEDIFF (hour, e.[Date & Time Started], e.[Date & Time Finished])
FROM dbo.Event e
INNER JOIN INSERTED i on e.[Event ID] = i.[Event ID]
最后,还要指出这是完全不必要的触发器使用。使用计算列可以完成(也应该)。因此,如果您只想将列更改为:
ALTER TABLE dbo.Event
ALTER COLUMN [Duration] AS DATEDIFF(hour, [Date & Time Started], [Date & Time Finished])
您将始终拥有正确的持续时间而无需触发。