2010-01-08 9 views

Respuesta

38

Una solución alternativa podría ser para alterar el flujo de ejecución de la secuencia de comandos mediante la instrucción GOTO ...

DECLARE @RunScript bit; 
SET @RunScript = 0; 

IF @RunScript != 1 
BEGIN 
RAISERROR ('Raise Error does not stop processing, so we will call GOTO to skip over the script', 1, 1); 
GOTO Skipper -- This will skip over the script and go to Skipper 
END 

PRINT 'This is where your working script can go'; 
PRINT 'This is where your working script can go'; 
PRINT 'This is where your working script can go'; 
PRINT 'This is where your working script can go'; 

Skipper: -- Don't do nuttin! 

Advertencia! La muestra anterior se derivó de un ejemplo que obtuve de Merrill Aldrich. Antes de implementar ciegamente la declaración GOTO, le recomiendo que lea su tutorial en Flow control in T-SQL Scripts.

+1

¡Gracias, Jed! Me gusta su: ON Error exit ejemplo. –

+11

@Pedro: Esto fallará si agrega GO entre las secciones del script de trabajo porque GOT se aplica por lote. Debe tener GO para dividir la secuencia de comandos en lotes cuando tenga instrucciones CREATE, etc. que a menudo debe ser el primer comando de un lote. Ver los comentarios de chadhoc en otras respuestas – gbn

+1

Jed. Gracias por el enlace al "control de flujo", qué revelador: he pasado la última hora jugando con cada configuración en la que puedo pensar y llorando al pensar en cuántos guiones necesitaría corregir. :-( –

16

Por qué no simplemente añadir lo siguiente al comienzo de la secuencia de comandos

PRINT 'INACTIVE SCRIPT' 
RETURN 
+13

Tenga en cuenta que esto no funcionará si la secuencia de comandos contiene separadores de lotes (es decir, declaraciones GO) - la devolución solo regresará desde el primer lote. – chadhoc

+1

OH! ¡Eso es bueno saber! ¡Tal vez debería poner un/* al principio y un */al final! –

+0

Buen punto chadHoc, pensé que se refería a un procedimiento almacenado ... Gracias – Sparky

3

intente ejecutar esto como una secuencia de comandos TSQL

SELECT 1 
RETURN 
SELECT 2 
SELECT 3 

El retorno termina la ejecución.

RETURN (Transact-SQL)

Sale incondicionalmente de una consulta o procedimiento. RETURN es inmediato y se completó y se puede usar en cualquier punto para salir de un bloque de instrucciones de procedimiento, lote o . Las declaraciones que siguen RETORNO no se ejecutan.

+2

Una vez más, no ayudaría para un script que contiene separadores de lotes (es decir, declaraciones GO) - el retorno es específico del lote. – chadhoc

14

Para solucionar el problema RETURN/GO, puede poner RAISERROR ('Oi! Stop!', 20, 1) WITH LOG en la parte superior.

Esto cerrará la conexión del cliente según RAISERROR on MSDN.

El muy grande inconveniente es que tienes que ser administrador de sistemas para utilizar la gravedad 20.

Editar:

una simple demostración para contrarrestar el comentario de Jersey Tipo ...

RAISERROR ('Oi! Stop!', 20, 1) WITH LOG 
SELECT 'Will not run' 
GO 
SELECT 'Will not run' 
GO 
SELECT 'Will not run' 
GO 
+0

Nuevamente, esto solo funcionará en el lote actual. La ejecución comienza de nuevo al comienzo del siguiente lote (Después del GO). –

+0

@Jersey Dude: Estás equivocado.La conexión del cliente se cierra con una severidad de 20 o superior. Entonces no se ejecutarán más lotes. ¿O puedes probar lo contrario? – gbn

+0

@neves: ¿en serio? http://msdn.microsoft.com/en-us/library/aa238452(v=sql.80).aspx – gbn

34

n , no hay uno - usted tiene un par de opciones:

  1. Envuelve todo el script en un bloque if/end grande que simplemente se asegura que no sea verdadero (es decir "si 1 = 2 begin" - esto solo funcionará, sin embargo, si el script no incluye ninguna declaración GO (ya que estos indican un nuevo lote)

  2. Use la declaración return en la parte superior (nuevamente, limitada por el lote) separadores)

  3. utilice un enfoque basado en la conexión, lo que garantizará la no ejecución de todo el guión (de conexión completo para ser más exactos) - usar algo así como un 'SET PARSEONLY ON' o 'SET NOEXEC ON' en la parte superior de la secuencia de comandos. Esto asegurará que todas las declaraciones en la conexión (o hasta que dicha declaración establecida se desactive) no se ejecutarán y en su lugar solo se analizarán/compilarán.

  4. Utilice un bloque de comentarios para comentar todo el script (es decir/ * Y * /)

EDIT: Demostración de que la declaración de 'retorno' es lote específico - en cuenta que seguirá viendo conjuntos de resultados después de los rendimientos:

select 1 
return 
go 
select 2 
return 
select 3 
go 
select 4 
return 
select 5 
select 6 
go 
2

A pesar de su muy descripción explícita y contundente, RETORNO no funcionó para mí dentro de un procedimiento almacenado (para omitir la ejecución posterior). Tuve que modificar la lógica de la condición. Que sucede tanto en SQL 2008, 2008 R2:

create proc dbo.prSess_Ins 
(
    @sSessID varchar(32) 
, @idSess  int out 
) 
as 
begin 
    set nocount on 

    select @id= idSess 
     from tbSess 
     where sSessID = @sSessID 

    if @idSess > 0 return -- exit sproc here 

    begin tran 
     insert tbSess (sSessID) values (@sSessID) 
     select @idSess= scope_identity() 
    commit 
end 

tuvo que ser cambiado en:

if @idSess is null 
    begin 
     begin tran 
      insert tbSess (sSessID) values (@sSessID) 
      select @idSess= scope_identity() 
     commit 
    end 

Descubierto como resultado de la búsqueda de filas duplicadas. Las IMPRESIONES de depuración confirmaron que @idSess tenía un valor mayor que cero en la verificación IF. ¡RETORNO no interrumpió la ejecución!

+2

Más tarde descubrí que si especifico un valor de retorno (como en 'return 1'), RETURN funciona como se esperaba: salir del sproc. – Astrogator

7

RAISERROR con gravedad 20 se reportará como un error en el Visor de eventos.

Puede usar SET PARSEONLY ON; (o NOEXEC). Al final del script, usa GO SET PARSEONLY OFF;

SET PARSEONLY ON; 
-- statement between here will not run 

SELECT 'THIS WILL NOT EXEC'; 

GO 
-- statement below here will run 

SET PARSEONLY OFF; 
2

Aquí hay una manera algo complicada de hacerlo que funciona con GO-batches, mediante el uso de una variable "global".

if object_id('tempdb..#vars') is not null 
begin 
    drop table #vars 
end 

create table #vars (continueScript bit) 
set nocount on 
    insert #vars values (1) 
set nocount off 

-- Start of first batch 
if ((select continueScript from #vars)=1) begin 

    print '1' 

    -- Conditionally terminate entire script 
    if (1=1) begin 
    set nocount on 
     update #vars set continueScript=0 
    set nocount off 
    return 
    end 

end 
go 

-- Start of second batch 
if ((select continueScript from #vars)=1) begin 

    print '2' 

end 
go 

Y aquí está la misma idea utilizada con una transacción y un bloque de prueba/captura para cada GO-batch. Usted puede tratar de cambiar las diversas condiciones y/o dejar que se genera un error (división por 0, ver comentarios) para probar cómo se comporta:

if object_id('tempdb..#vars') is not null 
begin 
    drop table #vars 
end 

create table #vars (continueScript bit) 
set nocount on 
    insert #vars values (1) 
set nocount off 

begin transaction; 
    -- Batch 1 starts here 
    if ((select continueScript from #vars)=1) begin 
    begin try 
     print 'batch 1 starts' 

     if (1=0) begin 
     print 'Script is terminating because of special condition 1.' 
     set nocount on 
      update #vars set continueScript=0 
     set nocount off 
     return 
     end 

     print 'batch 1 in the middle of its progress' 

     if (1=0) begin 
     print 'Script is terminating because of special condition 2.' 
     set nocount on 
      update #vars set continueScript=0 
     set nocount off 
     return 
     end 

     set nocount on 
     -- use 1/0 to generate an exception here 
     select 1/1 as test 
     set nocount off 

    end try 
    begin catch 
     set nocount on 
     select 
      error_number() as errornumber 
      ,error_severity() as errorseverity 
      ,error_state() as errorstate 
      ,error_procedure() as errorprocedure 
      ,error_line() as errorline 
      ,error_message() as errormessage; 
     print 'Script is terminating because of error.' 
     update #vars set continueScript=0 
     set nocount off 
     return 
    end catch; 

    end 
    go 

    -- Batch 2 starts here 
    if ((select continueScript from #vars)=1) begin 

    begin try 
     print 'batch 2 starts' 

     if (1=0) begin 
     print 'Script is terminating because of special condition 1.' 
     set nocount on 
      update #vars set continueScript=0 
     set nocount off 
     return 
     end 

     print 'batch 2 in the middle of its progress' 

     if (1=0) begin 
     print 'Script is terminating because of special condition 2.' 
     set nocount on 
      update #vars set continueScript=0 
     set nocount off 
     return 
     end 

     set nocount on 
     -- use 1/0 to generate an exception here 
     select 1/1 as test 
     set nocount off 

    end try 
    begin catch 
     set nocount on 
     select 
      error_number() as errornumber 
      ,error_severity() as errorseverity 
      ,error_state() as errorstate 
      ,error_procedure() as errorprocedure 
      ,error_line() as errorline 
      ,error_message() as errormessage; 
     print 'Script is terminating because of error.' 
     update #vars set continueScript=0 
     set nocount off 
     return 
    end catch; 

    end 
    go 

if @@trancount > 0 begin 
    if ((select continueScript from #vars)=1) begin 
    commit transaction 
    print 'transaction committed' 
    end else begin 
    rollback transaction; 
    print 'transaction rolled back' 
    end 
end 
1

Sé que la pregunta es antigua y fue contestada correctamente en algunos diferentes maneras pero no hay respuesta como la mía que he usado en situaciones similares. Primera aproximación (muy básico):

IF (1=0) 
BEGIN 
    PRINT 'it will not go there' 
    -- your script here 
END 
PRINT 'but it will here' 

Segundo enfoque:

PRINT 'stop here' 
RETURN 
    -- your script here 
PRINT 'it will not go there' 

puede comprobarlo fácilmente por sí mismo para asegurarse de que se comporta como se esperaba.

Cuestiones relacionadas