有没有办法以一种只触发一次触发器的方式组合更新和插入语句?
我有一个具有(当前需要)触发器AFTER INSERT, UPDATE, DELETE
的特定表。现在我想更新一行并插入另一行,并且只触发一次触发器。
这一切都可能吗?
我已经尝试过MERGE-Statement但没有成功:触发器会在更新时触发一次,对插入部件触发一次。
答案 0 :(得分:1)
嗯,问题解决了我。我没有找到将语句组合成触发器的一个fire-event的方法。但是触发器以一种有趣的方式运行,这对我来说已经足够了:对触发器的两次调用都已经可以访问完全更新的数据。
只需执行以下语句,您就会明白我的意思。
CREATE TABLE Foo (V INT)
GO
CREATE TRIGGER tFoo ON Foo AFTER INSERT, UPDATE, DELETE
AS
SELECT 'inserted' AS Type, * FROM inserted
UNION ALL
SELECT 'deleted', * FROM deleted
UNION ALL
SELECT 'actual', * FROM Foo
GO
DELETE FROM Foo
INSERT Foo VALUES (1)
;MERGE INTO Foo
USING (SELECT 2 AS V) AS Source ON 1 = 0
WHEN NOT MATCHED BY SOURCE THEN DELETE
WHEN NOT MATCHED BY TARGET THEN INSERT (V) VALUES (Source.V);
结果,MERGE将调用两次触发器。但这两次," SELECT * FROM Foo"已经提供了完全更新的数据:将有一行值为2.值1已被删除。
这让我感到很惊讶:在调用delete-trigger之前,先调用insert-trigger并删除已删除的行。
仅插入"的值"和"删除"对应于delete-或insert-statement。
答案 1 :(得分:0)
您可以尝试这样的事情:
触发器将检查是否存在#temp表。
如果它不存在,则使用虚拟数据创建它。然后,它检查最近的值是否包含现在正在运行的相同用户(SPID)以及上次触发的时间是否在20秒内。
如果这些都是真的那么它将PRINT 'Do Nothing'
并删除表,否则它将执行你的触发器声明。
在触发器语句结束时,它会在表中插入SPID和当前日期时间。
此临时表应该与SPID连接一样长,如果您希望它持续更长时间使其成为## temp或真实表。
IF OBJECT_ID('tempdb..#temp') IS NULL
begin
Create table #temp(SPID int, dt datetime)
insert into #temp values (0, '2000-01-01')
end
If @@SPID = (select top 1 SPID from #temp order by dt desc)
and Convert(datetime,Convert(varchar(19),GETDATE(),121)) between
Convert(datetime,Convert(varchar(19),(Select top 1 dt from #temp order by dt desc),121)) and
Convert(datetime,Convert(varchar(19),DateAdd(second, 20, (select top 1 dt from #temp order by dt desc)),121))
begin
PRINT 'Do Nothing'
Drop table #temp
end
else
begin
--trigger statement
Insert into #temp values (@@SPID, GETDATE())
end