web-dev-qa-db-fra.com

SQL Server 2000: comment quitter une procédure stockée?

Comment puis-je quitter au milieu d'une procédure stockée?

J'ai une procédure stockée dans laquelle je veux sortir plus tôt (en essayant de la déboguer). J'ai essayé d'appeler RETURN et RAISERROR, et le sp continue à fonctionner:

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]

Je sais qu'il continue à fonctionner parce que je rencontre une erreur plus bas. Je ne vois aucun de mes empreintes. Si je commente le gros de la procédure stockée:

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]
   */

Ensuite, je ne reçois pas mon erreur et je vois les résultats:

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

La question est donc: comment puis-je sortir d'une procédure stockée dans SQL Server?

60
Ian Boyd

Vous pouvez utiliser RETURN pour arrêter immédiatement l'exécution d'une procédure stockée. Citation tirée de documentation en ligne :

Quitte sans condition une requête ou une procédure. RETURN est immédiat et complet et peut être utilisé à tout moment pour sortir d'un bloc de procédure, de lot ou d'instruction. Les instructions qui suivent RETURN ne sont pas exécutées.

Hors de paranoïa, j'ai essayé votre exemple et il sort les PRINT et arrête l'exécution immédiatement.

80
AdaTheDev

Sauf si vous spécifiez une gravité de 20 ou plus, raiserror n'arrêtera pas l'exécution. Voir le documentation MSDN .

La solution de contournement normale consiste à inclure un return après chaque raiserror:

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

Mettez-le dans un TRY/CATCH.

Lorsque RAISERROR est exécuté avec une gravité supérieure ou égale à 11 dans un bloc TRY, il transfère le contrôle au bloc CATCH associé.

Référence: MSDN .

EDIT: Cela fonctionne pour MSSQL 2005+, mais je vois que vous venez de préciser que vous travaillez sur MSSQL 2000. Je vais laisser cela ici pour référence.

10

j'ai compris pourquoi RETURN ne retourne pas inconditionnellement de la procédure stockée. L'erreur que je vois est pendant que la procédure stockée est en cours d'exécution compilée - pas lors de son exécution.

Considérons une procédure stockée imaginaire:

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

Même si cette procédure stord contient une erreur (c'est peut-être parce que les objets ont un nombre différent de colonnes, peut-être qu'il y a une colonne timestamp dans la table, peut-être que la procédure stockée n'existe pas), vous pouvez toujours enregistrez le. Vous pouvez le sauvegarder car vous référencez un serveur lié.

Mais lorsque vous exécutez la procédure stockée, SQL Server le compile et génère un plan de requête.

Mon erreur ne se produit pas à la ligne 114, elle est à ligne 114 SQL Server ne peut pas compiler la procédure stockée, c’est pourquoi elle échoue.

Et c'est pourquoi RETURN ne revient pas, car il n'a pas encore commencé.

9
Ian Boyd

Cela fonctionne ici.

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

Résultats

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

Cela ressemble à beaucoup de code mais la meilleure façon que j'ai trouvée de le faire.

    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

C'est parce que vous n'avez pas d'instructions BEGIN et END. Vous ne devriez pas voir les empreintes ou les erreurs d’exécution de cette instruction, mais seulement Statement Completed (ou quelque chose comme ça).

1
cjk