stop script para not error ejemplos ejemplo datos crear sql sql-server scripting exit

script - sql server raiserror stop execution



SQL Server: detener o interrumpir la ejecuciĆ³n de un script SQL (18)

¿Hay una manera de detener inmediatamente la ejecución de un script SQL en el servidor SQL, como un comando "break" o "exit"?

Tengo un script que realiza algunas validaciones y búsquedas antes de que empiece a hacer inserciones, y quiero que se detenga si falla alguna de las validaciones o búsquedas.


¿Es este un procedimiento almacenado? Si es así, creo que podría hacer una devolución, como "Return NULL";


El método de refinamiento adicional de Sglasses, las líneas anteriores fuerzan el uso del modo SQLCMD, y o bien trincha el guión si no usa el modo SQLCMD o usa :on error exit para salir en cualquier error
CONTEXT_INFO se utiliza para realizar un seguimiento del estado.

SET CONTEXT_INFO 0x1 --Just to make sure everything''s ok GO --treminate the script on any error. (Requires SQLCMD mode) :on error exit --If not in SQLCMD mode the above line will generate an error, so the next line won''t hit SET CONTEXT_INFO 0x2 GO --make sure to use SQLCMD mode ( :on error needs that) IF CONTEXT_INFO()<>0x2 BEGIN SELECT CONTEXT_INFO() SELECT ''This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)/nPlease abort the script!'' RAISERROR(''This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)/nPlease abort the script!'',16,1) WITH NOWAIT WAITFOR DELAY ''02:00''; --wait for the user to read the message, and terminate the script manually END GO ---------------------------------------------------------------------------------- ----THE ACTUAL SCRIPT BEGINS HERE-------------


En SQL 2012+, puedes usar THROW .

set noexec off begin transaction go <First batch, do something here> go if @@error != 0 set noexec on; <Second batch, do something here> go if @@error != 0 set noexec on; <... etc> declare @finished bit; set @finished = 1; SET noexec off; IF @finished = 1 BEGIN PRINT ''Committing changes'' COMMIT TRANSACTION END ELSE BEGIN PRINT ''Errors occured. Rolling back changes'' ROLLBACK TRANSACTION END

Desde MSDN:

Provoca una excepción y transfiere la ejecución a un bloque CATCH de una construcción TRY ... CATCH ... Si una construcción TRY ... CATCH no está disponible, la sesión finaliza. Se establecen el número de línea y el procedimiento donde se produce la excepción. La gravedad se establece en 16.


Esta fue mi solución:

...

BEGIN raiserror(''Invalid database'', 15, 10) rollback transaction return END


Extendí la solución on / off de noexec con éxito con una transacción para ejecutar el script de una manera total o nada.

THROW 51000, ''Stopping execution because validation failed.'', 0; PRINT ''Still Executing''; -- This doesn''t execute with THROW

Al parecer, el compilador "entiende" la variable @finished en el SI, incluso si hubo un error y la ejecución fue deshabilitada. Sin embargo, el valor se establece en 1 solo si la ejecución no se deshabilitó. Por lo tanto, puedo cometer o deshacer la transacción de manera adecuada.


Gracias por la respuesta!

raiserror() funciona bien, pero no debes olvidar la declaración de return , de lo contrario, el script continúa sin errores. (¡hense el raiserror no es un "throwerror" ;-)) y por supuesto haciendo un rollback si es necesario!

raiserror() es agradable decirle a la persona que ejecuta el script que algo salió mal.


Le sugeriría que envuelva su bloque de código apropiado en un bloque try catch. Luego puede usar el evento Raiserror con una severidad de 11 para romper el bloque catch si lo desea. Si solo desea raiserrors pero continuar la ejecución dentro del bloque try, use una severidad más baja.

¿Tener sentido?

Saludos john

[Editado para incluir la referencia de BOL]

http://msdn.microsoft.com/en-us/library/ms175976(SQL.90).aspx


Ninguno de estos trabajos con declaraciones ''GO''. En este código, independientemente de si la gravedad es 10 u 11, se obtiene la declaración PRINT final.

Script de prueba:

-- ================================= PRINT ''Start Test 1 - RAISERROR'' IF 1 = 1 BEGIN RAISERROR(''Error 1, level 11'', 11, 1) RETURN END IF 1 = 1 BEGIN RAISERROR(''Error 2, level 11'', 11, 1) RETURN END GO PRINT ''Test 1 - After GO'' GO -- ================================= PRINT ''Start Test 2 - Try/Catch'' BEGIN TRY SELECT (1 / 0) AS CauseError END TRY BEGIN CATCH SELECT ERROR_MESSAGE() AS ErrorMessage RAISERROR(''Error in TRY, level 11'', 11, 1) RETURN END CATCH GO PRINT ''Test 2 - After GO'' GO

Resultados:

Start Test 1 - RAISERROR Msg 50000, Level 11, State 1, Line 5 Error 1, level 11 Test 1 - After GO Start Test 2 - Try/Catch CauseError ----------- ErrorMessage -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Divide by zero error encountered. Msg 50000, Level 11, State 1, Line 10 Error in TRY, level 11 Test 2 - After GO

La única forma de hacer que esto funcione es escribir el script sin instrucciones GO . A veces eso es fácil. A veces es bastante difícil. (Use algo como IF @error <> 0 BEGIN ... )


No usaría RAISERROR- SQL tiene sentencias IF que pueden usarse para este propósito. Realice su validación y búsquedas y establezca variables locales, luego use el valor de las variables en las declaraciones IF para hacer condicionales las inserciones.

No necesitarías verificar un resultado variable de cada prueba de validación. Por lo general, podría hacer esto con una sola variable de marca para confirmar todas las condiciones aprobadas:

declare @valid bit set @valid = 1 if -- Condition(s) begin print ''Condition(s) failed.'' set @valid = 0 end -- Additional validation with similar structure -- Final check that validation passed if @valid = 1 begin print ''Validation succeeded.'' -- Do work end

Incluso si su validación es más compleja, solo necesita unas pocas variables de marca para incluirlas en su (s) control (es) final (es).


Puede utilizar la declaración GOTO. Prueba esto. Este es el uso completo para usted.

WHILE(@N <= @Count) BEGIN GOTO FinalStateMent; END FinalStatement: Select @CoumnName from TableName


Puedes alterar el flujo de ejecución usando sentencias GOTO :

IF @ValidationResult = 0 BEGIN PRINT ''Validation fault.'' GOTO EndScript END /* our code */ EndScript:



Si puedes usar el modo SQLCMD, entonces el conjuro

:on error exit

(INCLUYENDO los dos puntos) hará que RAISERROR realmente detenga el script. P.ej,

:on error exit IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[dbo].[SOMETABLE]'') AND type in (N''U'')) RaisError (''This is not a Valid Instance Database'', 15, 10) GO print ''Keep Working''

saldrá:

Msg 50000, Level 15, State 10, Line 3 This is not a Valid Instance Database ** An error was encountered during execution of batch. Exiting.

y el lote se detendrá. Si el modo SQLCMD no está activado, obtendrá un error de análisis sobre los dos puntos. Desafortunadamente, no es completamente a prueba de balas, ya que si el script se ejecuta sin estar en modo SQLCMD, ¡SQL Managment Studio supera los errores de tiempo de análisis! Aún así, si los estás ejecutando desde la línea de comandos, esto está bien.


Si simplemente está ejecutando un script en Management Studio, y desea detener la ejecución o la transacción de retrotracción (si se usa) en el primer error, entonces la mejor manera de hacerlo es usar el bloque try catch (SQL 2005 en adelante). Esto funciona bien en Management studio si está ejecutando un archivo de script. Proc almacenado siempre puede usar esto también.


Simplemente use un RETURN (funcionará tanto dentro como fuera de un procedimiento almacenado).


Utilizo RETURN aquí todo el tiempo, funciona en script o en un Stored Procedure

Asegúrate de ROLLBACK la transacción si estás en uno, de lo contrario, RETURN inmediatamente resultará en una transacción abierta sin confirmar.


usted podría envolver su declaración SQL en un bucle WHILE y usar BREAK si es necesario

WHILE 1 = 1 BEGIN -- Do work here -- If you need to stop execution then use a BREAK BREAK; --Make sure to have this break at the end to prevent infinite loop END


El método raiserror

raiserror(''Oh no a fatal error'', 20, -1) with log

Esto terminará la conexión, lo que impedirá que el resto del script se ejecute.

Tenga en cuenta que tanto el nivel de gravedad 20 o superior como la opción WITH LOG son necesarios para que funcione de esta manera.

Esto incluso funciona con declaraciones GO, por ejemplo.

print ''hi'' go raiserror(''Oh no a fatal error'', 20, -1) with log go print ''ho''

Te dará la salida:

hi Msg 2745, Level 16, State 2, Line 1 Process ID 51 has raised user error 50000, severity 20. SQL Server is terminating this process. Msg 50000, Level 20, State 1, Line 1 Oh no a fatal error Msg 0, Level 20, State 0, Line 0 A severe error occurred on the current command. The results, if any, should be discarded.

Observe que ''ho'' no está impreso.

CUEVAS:

  • Esto solo funciona si ha iniciado sesión como administrador (función ''sysadmin'') y también lo deja sin conexión a la base de datos.
  • Si NO ha iniciado sesión como administrador, la llamada RAISEERROR () fallará y la secuencia de comandos continuará ejecutándose .
  • Cuando se invoca con sqlcmd.exe, se informará el código de salida 2745.

Referencia: http://www.mydatabasesupport.com/forums/ms-sqlserver/174037-sql-server-2000-abort-whole-script.html#post761334

El método noexec

Otro método que funciona con sentencias GO se set noexec on . Esto hace que el resto del script se salte. No finaliza la conexión, pero debe apagar noexec nuevamente antes de que se ejecute cualquier comando.

Ejemplo:

print ''hi'' go print ''Fatal error, script will not continue!'' set noexec on print ''ho'' go -- last line of the script set noexec off -- Turn execution back on; only needed in SSMS, so as to be able -- to run this script again in the same session.