SQL Server 2000: ¿Cómo salir de un procedimiento almacenado?


¿Cómo puedo salir en medio de un procedimiento almacenado?

Tengo un procedimiento almacenado en el que quiero salir temprano (mientras intento depurarlo). He intentado llamar RETURN y RAISERROR, y el sp sigue corriendo:

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]

Sé que se sigue ejecutando porque encuentro un error más abajo. No veo ninguna de mis impresiones. Si comento la mayor parte del procedimiento almacenado:

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

Entonces no recibo mi error, y veo los resultados:

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

Así que el la pregunta es: ¿cómo puedo salir de un procedimiento almacenado en SQL Server?

Author: Leigh, 2009-12-08

7 answers

Puede usar RETURN para detener la ejecución de un procedimiento almacenado inmediatamente. Cita tomada de Libros en Línea:

Sale incondicionalmente de una consulta o procedimiento. LA devolución es inmediata y completo y se puede utilizar en cualquier momento para salir de un procedimiento, lote, o bloque de declaración. Declaraciones que seguir RETORNO no se ejecutan.

Por paranoia, probé el ejemplo y muestra las impresiones y detiene la ejecución inmediatamente.

 76
Author: AdaTheDev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-07 12:39:58

A menos que especifique una severidad de 20 o superior, raiserror no detendrá la ejecución. Vea la documentación de MSDN .

La solución normal es incluir un return después de cada raiserror:

if @whoops = 1
    begin
    raiserror('Whoops!', 18, 1)
    return -1
    end
 27
Author: Andomar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-07 21:10:29

Ponlo en un TRY/CATCH.

Cuando RAISERROR se ejecuta con una severidad de 11 o superior en un bloque TRY, transfiere el control a los asociados Bloque de captura

Referencia: MSDN .

EDIT: Esto funciona para MSSQL 2005+, pero veo que ahora ha aclarado que está trabajando en MSSQL 2000. Dejaré esto aquí como referencia.

 10
Author: Forgotten Semicolon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-07 21:24:20

Descubrí por qué RETURN no está regresando incondicionalmente del procedimiento almacenado. El error que estoy viendo es mientras el procedimiento almacenado se está compilando - no cuando se está ejecutando.

Considere un procedimiento almacenado imaginario:

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

Aunque este stord proedure contiene un error (tal vez es porque los objetos tienen un número diferente de columnas, tal vez hay una columna de marca de tiempo en la tabla, tal vez el procedimiento almacenado no existe), todavía puede guárdalo. Puedes guardarlo porque estás haciendo referencia a un servidor vinculado.

Pero cuando realmente ejecuta el procedimiento almacenado, SQL Server entonces lo compila y genera un plan de consulta.

Mi error es no sucediendo en la línea 114, es en línea 114. SQL Server no puede compilar el procedimiento almacenado, por eso está fallando.

Y es por eso que RETURN no regresa, porque aún no ha comenzado .

 8
Author: Ian Boyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-07 21:53:55

Esto funciona aquí.

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

Devuelve

before raiserror
Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 7
this is a raised error
 4
Author: Damir Sudarevic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-07 21:27:43

Esto parece un montón de código, pero la mejor manera que he encontrado para hacerlo.

    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
Author: JDPeckham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-24 19:58:43

Es porque no tienes declaraciones BEGIN y END. No deberías ver las impresiones, o los errores que ejecutan esta instrucción, solo Statement Completed (o algo así).

 1
Author: cjk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-07 22:00:34