it-swarm.com.de

SQL Server 2000: Beenden einer gespeicherten Prozedur

Wie kann ich mitten in einer gespeicherten Prozedur beenden?

Ich habe eine gespeicherte Prozedur, bei der ich früh aussteigen möchte (während ich versuche, sie zu debuggen). Ich habe versucht, RETURN und RAISERROR aufzurufen, und der SP läuft weiter:

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]

Ich weiß, dass es weiterläuft, weil ich weiter unten auf einen Fehler stoße. Ich sehe keine meiner Drucke. Wenn ich den Großteil der gespeicherten Prozedur auskommentiere:

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

Dann bekomme ich meinen Fehler nicht und sehe die Ergebnisse:

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

Die Frage ist also: Wie kann ich eine gespeicherte Prozedur in SQL Server beenden?

60
Ian Boyd

Sie können RETURN verwenden, um die Ausführung einer gespeicherten Prozedur sofort zu stoppen. Zitat aus Books Online :

Beendet bedingungslos eine Abfrage oder Prozedur. RETURN ist sofort und vollständig und kann jederzeit zum Verlassen einer Prozedur, eines Stapels oder eines Anweisungsblocks verwendet werden. Anweisungen, die auf RETURN folgen, werden nicht ausgeführt.

Aus Paranoia habe ich dein Beispiel ausprobiert und es gibt die PRINTs aus und stoppt die Ausführung sofort.

80
AdaTheDev

Wenn Sie keinen Schweregrad von 20 oder höher angeben, wird die Ausführung von raiserror nicht angehalten. Siehe MSDN-Dokumentation .

Die normale Problemumgehung besteht darin, nach jedem return ein raiserror einzufügen:

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

Gib es in ein TRY/CATCH.

Wenn RAISERROR mit einem Schweregrad von 11 oder höher in einem TRY-Block ausgeführt wird, überträgt es die Kontrolle an den zugeordneten CATCH-Block

Referenz: MSDN .

BEARBEITEN: Dies funktioniert für MSSQL 2005+, aber ich sehe, dass Sie jetzt klargestellt haben, dass Sie an MSSQL 2000 arbeiten. Ich lasse dies hier für Referenz.

10

ich habe herausgefunden, warum RETURN nicht unbedingt von der gespeicherten Prozedur zurückkehrt. Der Fehler, den ich sehe, ist, während die gespeicherte Prozedur kompiliert - nicht, wenn es ausgeführt wird.

Betrachten Sie eine imaginäre gespeicherte Prozedur:

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

Auch wenn diese Prozedur einen Fehler enthält (vielleicht weil die Objekte eine andere Anzahl von Spalten haben, vielleicht gibt es eine Zeitstempelspalte in der Tabelle, vielleicht existiert die gespeicherte Prozedur nicht), können Sie trotzdem speichern es. Sie können es speichern, da Sie auf einen Verbindungsserver verweisen.

Wenn Sie jedoch die gespeicherte Prozedur tatsächlich ausführen, dann kompiliert ​​und generiert einen Abfrageplan.

Mein Fehler ist nicht passiert ​​in Zeile 114, es ist passiert ​​in Zeile 114. SQL Server kann die gespeicherte Prozedur nicht kompilieren, deshalb schlägt sie fehl.

Und deshalb kehrt RETURN nicht zurück, weil es noch nicht einmal gestartet ist.

9
Ian Boyd

Das funktioniert hier.

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

Kehrt zurück

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

Dies scheint eine Menge Code, aber der beste Weg, den ich gefunden habe, um es zu tun.

    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

Es liegt daran, dass Sie keine Anweisungen BEGIN und END haben. Sie sollten die Ausdrucke oder Fehler bei der Ausführung dieser Anweisung nicht sehen, sondern nur Statement Completed (oder etwas ähnliches).

1
cjk