在延迟一段时间后从触发器执行存储过程

时间:2012-06-28 07:50:22

标签: sql-server sql-server-2008 stored-procedures sql-server-2000 sql-server-express

我想从触发器调用存储过程, 如何在x分钟后执行该存储过程? 我正在寻找WAITFOR DELAY

以外的其他内容

感谢

2 个答案:

答案 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分钟内,记录实际上不会被处理。