Команда T-SQL STOP или ABORT в SQL Server

есть ли команда в Microsoft SQL Server T-SQL, чтобы сообщить скрипту остановить обработку? У меня есть скрипт, который я хочу сохранить для архивных целей, но я не хочу, чтобы запустить его.

9 ответов


альтернативным решением может быть изменение потока выполнения вашего скрипта с помощью 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!

предупреждение! Вышеприведенный образец был получен из примера, который я получил от Меррилла Олдрича. Прежде чем реализовать GOTO заявление вслепую, я рекомендую вам прочитать его учебник о управление потоком в скриптах T-SQL.


нет, нет-у вас есть несколько вариантов:

  1. оберните весь скрипт в большой блок if / end, который просто гарантирован, чтобы не быть истинным (т. е. "если 1=2 begin" - это будет работать только в том случае, если скрипт не включает никаких операторов GO (как те указывают на новый пакет)

  2. Используйте оператор return вверху (опять же, ограниченный разделителями пакетов)

  3. используйте подход на основе соединения, который будет убедитесь, что не выполняется для всего скрипта (все соединение, чтобы быть более точным) - используйте что-то вроде 'УСТАНОВИТЬ PARSEONLY ON' или 'УСТАНОВИТЬ NOEXEC НА' в верхней части скрипта. Это гарантирует, что все операторы в соединении (или пока указанный оператор set не выключен) не будут выполняться и вместо этого будут проанализированы/скомпилированы только.

  4. используйте блок комментариев, чтобы прокомментировать весь скрипт (т. е. / * И */)

EDIT: демонстрация того, что инструкция "return" является пакетной-обратите внимание, что вы будете продолжать видеть результирующие наборы после возвращения:

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

почему бы просто не добавить в начале скрипта

PRINT 'INACTIVE SCRIPT'
RETURN

чтобы обойти проблему возврата / GO, вы можете поставить RAISERROR ('Oi! Stop!', 20, 1) WITH LOG в верхней части.

это закроет клиентское соединение согласно RAISERROR на MSDN.

очень большой недостаток-надо быть сисадмином, чтобы использовать тяжести 20.

Edit:

простая демонстрация, чтобы противостоять комментарию Джерси-чувака...

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

RAISERROR с серьезностью 20 сообщит об ошибке в средстве просмотра событий.

вы можете использовать SET PARSEONLY ON; (или NOEXEC). В конце скрипта используйте 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;

попробуйте запустить это как сценарий TSQL

SELECT 1
RETURN
SELECT 2
SELECT 3

возврат завершает выполнение.

RETURN (Transact-SQL)

безусловный выход из запроса или процедура. Возвращение немедленно и полный и может быть использовано в любой момент для выхода из процедуры, пакета или блок операторов. Заявления, которые последующие возвраты не выполняются.


несмотря на его очень явное и сильное описание, RETURN не работал для меня внутри хранимой процедуры (чтобы пропустить дальнейшее выполнение). Мне пришлось изменить логику условий. Происходит на обоих 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

пришлось изменить на:

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

обнаружен в результате нахождения дублированных строк. Отладка отпечатков подтвердила, что значение @idSess было больше нуля в if check-RETURN не нарушило выполнение!


вот несколько kludgy способ сделать это, который работает с GO-пакетами, используя "глобальную" переменную.

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

и вот та же идея, используемая с транзакцией и блоком try/catch для каждой GO-партии. Вы можете попытаться изменить различные условия и / или позволить ему генерировать ошибку (разделить на 0, см. комментарии), чтобы проверить, как он ведет себя:

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

Я знаю, что вопрос старый и получил правильный ответ несколькими различными способами, но нет ответа, как мой, который я использовал в подобных ситуациях. Первый подход (очень простой):

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

второй подход:

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

Вы можете легко проверить это самостоятельно, чтобы убедиться, что он ведет себя, как ожидалось.