Domanda T-SQL: un modo corretto per CHIUDERE / DISINSERIRE il cursore nel trigger di aggiornamento


Diciamo che ho un trigger come questo:

CREATE TRIGGER trigger1
   ON [dbo].[table1] 
   AFTER UPDATE
AS 
BEGIN               
    --declare some vars
    DECLARE @Col1 SMALLINT 
    DECLARE @Col1 TINYINT 

    --declare cursor        
    DECLARE Cursor1 CURSOR FOR 
    SELECT Col1, Col2 FROM INSERTED             

    --do the job
    OPEN Cursor1
    FETCH NEXT FROM Cursor1 INTO @Col1, @Col2

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF ...something...
        BEGIN           
            EXEC myProc1 @param1 = @Col1, @Param2 = @Col2
        END             
        ELSE
        IF ...something else...
        BEGIN           
            EXEC myProc2 @param1 = @Col1, @Param2 = @Col2
        END     

        FETCH NEXT FROM Cursor1 INTO @Col1, @Col2               
    END

    --clean it up       
    CLOSE Cursor1
    DEALLOCATE Cursor1                  
END

Voglio essere sicuro che Cursor1 sia sempre chiuso e deallocato. Persino myProc1 o myProc2 non riescono.

Devo usare il blocco try / catch?


15
2017-09-11 09:33


origine


risposte:


Sì, usa TRY / CATCH ma assicurati di deallocarti ecc. Dopo. Sfortunatamente, non c'è ancora in SQL Server.

Tuttavia, ti suggerisco di avvolgerlo in un altro tentativo / cattura

CREATE TRIGGER trigger1 ON [dbo].[table1] AFTER UPDATE
AS 
BEGIN                           
    --declare some vars
    DECLARE @Col1 SMALLINT, @Col1 TINYINT 

    BEGIN TRY
        --declare cursor            
        DECLARE Cursor1 CURSOR FOR 
        SELECT Col1, Col2 FROM INSERTED                     

        --do the job
        OPEN Cursor1
        FETCH NEXT FROM Cursor1 INTO @Col1, @Col2

        WHILE @@FETCH_STATUS = 0
        BEGIN
            IF ...something...
                    EXEC myProc1 @param1 = @Col1, @Param2 = @Col2
            ELSE
            IF ...something else...
                    EXEC myProc2 @param1 = @Col1, @Param2 = @Col2

            FETCH NEXT FROM Cursor1 INTO @Col1, @Col2                               
        END
    END TRY
    BEGIN CATCH
        --do what you have to
    END CATCH

    BEGIN TRY
        --clean it up               
        CLOSE Cursor1
        DEALLOCATE Cursor1                                  
    END TRY
    BEGIN CATCH
        --do nothing
    END CATCH
END

Se un cursore in un trigger è una buona idea è una questione diversa ...


15
2017-09-15 05:28



È possibile utilizzare la funzione CURSOR_STATUS ().

if CURSOR_STATUS('global','cursor_name') >= 0 
begin
 close cursor_name
  deallocate cursor_name 
end

riferimento: http://msdn.microsoft.com/en-us/library/ms177609.aspx


37
2018-01-20 20:20



Quello che dovresti fare non usare mai mai un cursore in un trigger. Scrivere invece un codice basato su set corretto. Se qualcuno ha importato dei dati nella tua tabella di 100.000 nuovi record, bloccherai la tabella per ore e interromperai il tuo database. È una pratica molto povera usare un cursore in un trigger.


1
2017-09-11 13:18