risposta

9

Hai un processo di SQL Agent eseguito regolarmente e tira memorizzato parametri della procedura da una tabella - le righe devono indicare anche quando dovrebbe verificarsi la loro corsa della stored procedure , quindi il lavoro di SQL Agent selezionerà solo le righe scadute/leggermente scadute. Dovrebbe eliminare le righe o contrassegnarle dopo aver chiamato la stored procedure.

Quindi, nel trigger, inserire semplicemente una nuova riga in questa stessa tabella.

Si non si desidera mettere nulla in un trigger che influenzerà l'esecuzione della transazione originale in alcun modo - sicuramente non si vuole causare alcun ritardo, o interagire con qualcosa al di fuori dello stesso Banca dati.


Ad esempio, se la stored procedure è

CREATE PROCEDURE DoMagic 
    @Name varchar(20), 
    @Thing int 
AS 
    ... 

Poi ci piacerebbe creare una tabella:

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 
) 

E il processo di SQL agente avrebbe fatto:

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 

E il trigger avrebbe solo:

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 

Se si esegue in un'edizione che non supporta l'agente, quindi potrebbe essere necessario fingere. Quello che ho fatto in passato è quello di creare una stored procedure che contiene i "poveri processi dell'agente mans", qualcosa di simile a:

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 

Quindi, creare una seconda stored procedure, questa volta nel database master, che attende 30 secondi e poi chiama la prima procedura:

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

e poi, segnare questa procedura come una procedura di avvio, utilizzando sp_procoption:

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

E riavvia il servizio: ora avrai una query in esecuzione continua.

+0

Scusate se dimenticate di aggiungere il tag sql-express. –

+1

@MohammedRabee - C'è qualcosa che non va con i tag allora - Non c'è SQL Server 2000 Express. C'era MSDE, ma la prima edizione Express era del 2005. Puoi correggere per favore? –

+0

Voglio che funzioni su sql-server2000 e sql-server2008express –

1

Avevo una situazione simile in cui prima ho elaborato i record inseriti nella tabella con il trigger, volevo assicurarmi che anche tutti i relativi dati relativi nelle tabelle relazionali fossero presenti.

La mia soluzione era quella di creare un tavolo scratch che era popolato dal trigger di inserimento sul primo tavolo.

La tabella iniziale aveva un flag aggiornato, (valore predefinito impostato su 0) e un campo di inserimento get date() e l'identificatore pertinente dalla tabella principale.

Ho quindi creato un processo pianificato per eseguire il loop sulla tabella zero ed eseguire qualsiasi processo che volevo eseguire su ogni record singolarmente, e aggiornando il 'flag aggiornato' come ogni record è stato elaborato.

MA, qui è dove sono stato un pochino intelligente, nel ciclo sul processo alla ricerca di record nella tabella graffio che aveva un update flag = 0, ho aggiunto anche la clausola di ANDAND datediff(mi, Updated_Date, getdate())> 5. Quindi il record non sarebbe stato elaborato fino a 5 minuti DOPO che è stato inserito nel tavolo scratch.