7

トリガーからストアドプロシージャを呼び出したいのですが、x分後にそのストアドプロシージャを実行するにはどうすればよいですか?私は以外のものを探していますWAITFOR DELAY

ありがとう

4

2 に答える 2

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

次に、2番目のストアドプロシージャを作成します。今回はmasterデータベースに30秒待機してから、最初のプロシージャを呼び出します。

CREATE PROCEDURE BootstrapBackgroundTask
AS
    WAITFOR DELAY '00:00:30'
    EXEC YourDB..DoBackgroundTask

次に、次のコマンドを使用して、このプロシージャをスタートアッププロシージャとしてマークしますsp_procoption

EXEC sp_procoption N'BootstrapBackgroundTask', 'startup', 'on'

そして、サービスを再起動します。これで、クエリが継続的に実行されます。

于 2012-06-28T07:58:01.727 に答える
1

テーブルに挿入されたレコードをトリガーで処理する前に、リレーショナルテーブル内の関連するすべてのデータもそこにあることを確認したいという、似たような状況がありました。

私の解決策は、最初のテーブルに挿入トリガーが設定されたスクラッチテーブルを作成することでした。

スクラッチテーブルには、更新されたフラグ(デフォルトは0に設定)、挿入get date()日付フィールド、およびメインテーブルの関連する識別子がありました。

次に、スクラッチテーブルをループして、各レコードに対して個別に実行したいプロセスを実行するスケジュールされたプロセスを作成し、各レコードが処理されるたびに「更新されたフラグ」を更新しました。

しかし、ここで私は少し賢くなりました。ループオーバープロセスで、を含むスクラッチテーブル内のレコードを検索し、の句update flag = 0も追加しました。したがって、レコードは、スクラッチテーブルに挿入されてから5分後まで実際には処理されません。ANDAND datediff(mi, Updated_Date, getdate())> 5

于 2013-03-26T10:19:02.010 に答える