Команда T-SQL STOP или ABORT в SQL Server - PullRequest
49 голосов
/ 08 января 2010

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

Ответы [ 9 ]

44 голосов
/ 04 апреля 2012

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

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

35 голосов
/ 08 января 2010

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

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

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

  3. Используйте подход, основанный на подключении, который обеспечит невыполнение всего сценария (точнее, всего соединения) - используйте что-то вроде 'SET PARSEONLY ON' или 'SET NOEXEC ON' вверху скрипта. Это гарантирует, что все операторы в соединении (или до тех пор, пока указанный оператор set не будет отключен) не будут выполняться, а будут только проанализированы / скомпилированы.

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

РЕДАКТИРОВАТЬ: Демонстрация того, что оператор 'return' является специфическим для пакета - обратите внимание, что вы продолжите видеть наборы результатов после возврата:

select 1
return
go
select 2
return
select 3
go
select 4
return
select 5
select 6
go
17 голосов
/ 08 января 2010

Почему бы просто не добавить следующее в начало сценария

PRINT 'INACTIVE SCRIPT'
RETURN
14 голосов
/ 08 января 2010

Чтобы обойти проблему 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
8 голосов
/ 22 марта 2012

RAISERROR со степенью серьезности 20 сообщит об ошибке в Event Viewer.

Вы можете использовать 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;
3 голосов
/ 18 марта 2015

Вот несколько хитрый способ сделать это, который работает с 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
3 голосов
/ 08 января 2010

Попробуйте запустить его как скрипт TSQL

SELECT 1
RETURN
SELECT 2
SELECT 3

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

ВОЗВРАТ (Transact-SQL)

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

2 голосов
/ 18 июня 2011

Несмотря на очень явное и убедительное описание, 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

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

1 голос
/ 08 декабря 2016

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

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'

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

...