it-swarm.it

SQL Server 2000: come uscire da una procedura memorizzata?

Come posso uscire nel mezzo di una procedura memorizzata?

Ho una procedura memorizzata in cui desidero eseguire il salvataggio anticipato (mentre provo a eseguire il debug). Ho provato a chiamare RETURN e RAISERROR e lo sp continua a funzionare:

CREATE PROCEDURE dbo.Archive_Session @SessionGUID uniqueidentifier AS

    print 'before raiserror'
    raiserror('this is a raised error', 18, 1)
    print 'before return'
    return -1
    print 'after return'

[snip]

So che continua a funzionare perché riscontro un errore più in basso. Non vedo nessuno dei miei stampe. Se commento la maggior parte della procedura memorizzata:

CREATE PROCEDURE dbo.Archive_Session @SessionGUID uniqueidentifier AS

    print 'before raiserror'
    raiserror('this is a raised error', 18, 1)
    print 'before return'
    return -1
    print 'after return'

   /*
     [snip]
   */

Quindi non ricevo il mio errore e vedo i risultati:

before raiserror
Server: Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 5
this is a raised error
before return

Quindi la domanda è: come posso salvare una procedura memorizzata in SQL Server?

60
Ian Boyd

È possibile utilizzare RETURN per interrompere immediatamente l'esecuzione di una procedura memorizzata. Citazione tratta da Libri online :

Esce incondizionatamente da una query o una procedura. RETURN è immediato e completo e può essere utilizzato in qualsiasi momento per uscire da una procedura, un batch o un blocco di istruzioni. Le istruzioni che seguono RETURN non vengono eseguite.

Per paranoia, ho provato il tuo esempio e produce le STAMPE e interrompe immediatamente l'esecuzione.

80
AdaTheDev

Se non si specifica una severità di 20 o superiore, raiserror non interromperà l'esecuzione. Vedere documentazione MSDN .

La soluzione normale è includere un return dopo ogni raiserror:

if @whoops = 1
    begin
    raiserror('Whoops!', 18, 1)
    return -1
    end
28
Andomar

Mettilo in un TRY/CATCH.

Quando RAISERROR viene eseguito con una severità di 11 o superiore in un blocco TRY, trasferisce il controllo al blocco CATCH associato

Riferimento: MSDN .

EDIT: Funziona con MSSQL 2005+, ma vedo che ora hai chiarito che stai lavorando su MSSQL 2000. Lascio questo qui per riferimento.

10

ho capito perché RETURN non ritorna incondizionatamente dalla procedura memorizzata. L'errore che sto vedendo è durante l'esecuzione della procedura memorizzata compilata - non durante l'esecuzione.

Prendi in considerazione una procedura memorizzata immaginaria:

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

Anche se questa procedura stord contiene un errore (forse è perché gli oggetti hanno un numero differnet di colonne, forse c'è una colonna timestamp nella tabella, forse la procedura memorizzata non esiste), puoi comunque salva . Puoi salvarlo perché fai riferimento a un server collegato.

Ma quando in realtà esegui la procedura memorizzata, SQL Server quindi compila e genera un piano di query.

Il mio errore non è in corso sulla riga 114, è sulla riga 114 SQL Server non è in grado di compilare la procedura memorizzata, ecco perché non riesce.

Ed è per questo che RETURN non ritorna, perché non ha nemmeno iniziato ancora.

9
Ian Boyd

Questo funziona qui.

ALTER PROCEDURE dbo.Archive_Session
    @SessionGUID int
AS 
    BEGIN
        SET NOCOUNT ON
        PRINT 'before raiserror'
        RAISERROR('this is a raised error', 18, 1)
        IF @@Error != 0 
            RETURN
        PRINT 'before return'
        RETURN -1
        PRINT 'after return'
    END
go

EXECUTE dbo.Archive_Session @SessionGUID = 1

Ritorna

before raiserror
Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 7
this is a raised error
4
Damir Sudarevic

Sembra un sacco di codice ma il modo migliore che ho trovato per farlo.

    ALTER PROCEDURE Procedure
    AS

    BEGIN TRY
        EXEC AnotherProcedure
    END TRY
    BEGIN CATCH
        DECLARE @ErrorMessage NVARCHAR(4000);
        DECLARE @ErrorSeverity INT;
        DECLARE @ErrorState INT;

        SELECT 
            @ErrorMessage = ERROR_MESSAGE(),
            @ErrorSeverity = ERROR_SEVERITY(),
            @ErrorState = ERROR_STATE();

        RAISERROR (@ErrorMessage, -- Message text.
                   @ErrorSeverity, -- Severity.
                   @ErrorState -- State.
                   );
        RETURN --this forces it out
    END CATCH

--Stuff here that you do not want to execute if the above failed.    

    END --end procedure
4
JDPeckham

È perché non hai istruzioni BEGIN e END. Non dovresti vedere le stampe o errori nell'esecuzione di questa istruzione, solo Statement Completed (o qualcosa di simile).

1
cjk