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?
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.
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
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.
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 .
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
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
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í).
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