SQL Server中的T-SQL STOP或ABORT命令

Phi*_*enn 52 sql t-sql sql-server sql-scripts

Microsoft SQL Server T-SQL中是否有命令告诉脚本停止处理?我有一个脚本,我想保留用于存档目的,但我不希望任何人运行它.

Jed*_*Jed 46

另一种解决方案可能是使用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!
Run Code Online (Sandbox Code Playgroud)

警告!以上样本来自我从Merrill Aldrich获得的一个例子.在GOTO盲目实现语句之前,我建议您阅读他在T-SQL脚本中的Flow控制教程.

  • @Pedro:如果在工作脚本部分之间添加GO,这将失败,因为GOT适用于每批.当你有CREATE语句等通常必须是批处理中的第一个命令时,你必须有GO来将脚本分成批.请参阅chadhoc对其他答案的评论 (12认同)

boy*_*dc7 37

不,没有一个 - 你有几个选择:

  1. 将整个脚本包装在一个大的if/end块中,这个块确保不成立(即"如果1 = 2开始" - 这只有在脚本不包含任何GO语句时才会起作用(因为它们表示一个新的)批量)

  2. 使用顶部的return语句(再次,由批处理分隔符限制)

  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
Run Code Online (Sandbox Code Playgroud)

  • 我真的很惊讶没有停止执行的命令。只是...哇。 (2认同)
  • @JacobFW - 请参阅 Erland Somerskog 的 [优秀摘要](http://www.sommarskog.se/error_handling/Part2.html#:~:text=Every%20once%20in%20a%20while,something%20with%20error%20handling !):“每隔一段时间,我就会感觉到 SQL Server 是故意设计得尽可能地令人困惑。当他们计划发布新版本时,他们会互相询问这次我们可以做什么来迷惑用户?有时他们有点没有想法,但后来有人说_让我们做一些错误处理吧!_”(Erland 担任 SQL Server MVP 至少 20 年了) (2认同)

Spa*_*rky 18

为什么不简单地将以下内容添加到脚本的开头

PRINT 'INACTIVE SCRIPT'
RETURN
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果脚本包含批处理分隔符(即GO语句),则此操作无效 - 返回仅从第一批返回. (14认同)

gbn*_*gbn 14

要解决RETURN/GO问题,您可以将其置于RAISERROR ('Oi! Stop!', 20, 1) WITH LOG顶部.

这将根据MSDN上的RAISERROR关闭客户端连接.

非常大的缺点是你必须使用系统管理员来使用严重性20.

编辑:

一个简单的示威来反击泽西·杜德的评论......

RAISERROR ('Oi! Stop!', 20, 1)  WITH LOG
SELECT 'Will not run'
GO
SELECT 'Will not run'
GO
SELECT 'Will not run'
GO
Run Code Online (Sandbox Code Playgroud)


Cha*_*pol 8

严重性为20的RAISERROR将在事件查看器中报告为错误.

你可以使用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;
Run Code Online (Sandbox Code Playgroud)


Mag*_*nus 5

这是一种有点笨拙的方法,通过使用“全局”变量来处理 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
Run Code Online (Sandbox Code Playgroud)

这里与每个 GO-batch 的事务和 try/catch 块使用相同的想法。您可以尝试更改各种条件和/或让它生成错误(除以 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
Run Code Online (Sandbox Code Playgroud)