我想从触发器调用存储过程,
如何在x分钟后执行该存储过程?
我正在寻找WAITFOR DELAY
感谢
答案 0 :(得分:9)
拥有一个定期运行的SQL代理作业并从表中提取存储过程参数 - 这些行还应指示何时应该运行存储过程,因此SQL代理作业将仅选择到期/略微过期的行。它应该在调用存储过程后删除行或标记它们。
然后,在触发器中,只需在同一个表中插入一个新行。
你不想要以任何方式在触发器中放置任何会影响原始事务执行的内容 - 你绝对不希望造成任何延迟或与任何事物交互在同一个数据库之外。
例如,如果存储过程是
CREATE PROCEDURE DoMagic
@Name varchar(20),
@Thing int
AS
...
然后我们创建一个表:
CREATE TABLE MagicDue (
MagicID int IDENTITY(1,1) not null, --May not be needed if other columns uniquely identify
Name varchar(20) not null,
Thing int not null,
DoMagicAt datetime not null
)
SQL代理作业将执行:
WHILE EXISTS(SELECT * from MagicDue where DoMagicAt < CURRENT_TIMESTAMP)
BEGIN
DECLARE @Name varchar(20)
DECLARE @Thing int
DECLARE @MagicID int
SELECT TOP 1 @Name = Name,@Thing = Thing,@MagicID = MagicID from MagicDue where DoMagicAt < CURRENT_TIMESTAMP
EXEC DoMagic @Name,@Thing
DELETE FROM MagicDue where MagicID = @MagicID
END
触发器只有:
CREATE TRIGGER Xyz ON TabY after insert
AS
/*Do stuff, maybe calculate some values, or just a direct insert?*/
insert into MagicDue (Name,Thing,DoMagicAt)
select YName,YThing+1,DATEADD(minute,30,CURRENT_TIMESTAMP) from inserted
如果您在不支持代理的版本中运行,那么您可能必须伪造它。我过去所做的是创建一个包含“穷人代理人工作”的存储过程,如:
CREATE PROCEDURE DoBackgroundTask
AS
WHILE 1=1
BEGIN
/* Add whatever SQL you would have put in an agent job here */
WAITFOR DELAY '00:05:00'
END
然后,创建第二个存储过程,这次是在master
数据库中,等待30秒,然后调用第一个过程:
CREATE PROCEDURE BootstrapBackgroundTask
AS
WAITFOR DELAY '00:00:30'
EXEC YourDB..DoBackgroundTask
然后,使用sp_procoption
:
EXEC sp_procoption N'BootstrapBackgroundTask', 'startup', 'on'
然后重新启动服务 - 您现在将继续运行查询。
答案 1 :(得分:1)
我有类似的情况,在我用触发器处理插入表中的记录之前,我想确保关系表中的所有相关相关数据也在那里。
我的解决方案是创建一个临时表,该表由第一个表上的插入触发器填充。
临时表有一个更新的标志(默认设置为0),一个插入get date()
日期字段,以及主表中的相关标识符。
然后我创建了一个调度进程来遍历临时表,并分别对每条记录执行我想要执行的任何进程,并在处理每条记录时更新“updated flag”。
但是,这是我有点聪明的地方,在循环过程中查找具有update flag = 0
的临时表中的记录,我还添加了AND
的{{1}}子句}}。因此,在将记录插入临时表之后的5分钟内,记录实际上不会被处理。