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

发布于 2024-08-16 21:30:08 字数 79 浏览 6 评论 0原文

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

Is there a command in Microsoft SQL Server T-SQL to tell the script to stop processing?
I have a script that I want to keep for archival purposes, but I don't want anyone to run it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

仅此而已 2024-08-23 21:30:08

另一种解决方案可能是使用 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 脚本中的流控制

An alternate solution could be to alter the flow of execution of your script by using the GOTO statement...

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!

Warning! The above sample was derived from an example I got from Merrill Aldrich. Before you implement the GOTO statement blindly, I recommend you read his tutorial on Flow control in T-SQL Scripts.

番薯 2024-08-23 21:30:08

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

  1. 将整个脚本包装在一个大的 if/end 块中,只是确保不为真(即“if 1=2 begin” - 这只会但是,如果脚本不包含任何 GO 语句(因为这些语句指示新批次),则可以工作

  2. 使用顶部的 return 语句(同样,受批次分隔符限制)

  3. 使用基于连接的方法,这将确保整个脚本不执行(整个连接更准确) - 使用类似 '设置解析打开''SET NOEXEC ON' 位于脚本顶部。这将确保连接中的所有语句(或直到关闭所述 set 语句)都不会执行,而只会被解析/编译。

  4. 使用注释块注释掉整个脚本(即 /* 和 */)

编辑:演示 'return ' 语句是特定于批次的 - 请注意,您将在返回后继续看到结果集:

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

No, there isn't one - you have a couple of options:

  1. Wrap the whole script in a big if/end block that is simply ensured to not be true (i.e. "if 1=2 begin" - this will only work however if the script doesn't include any GO statements (as those indicate a new batch)

  2. Use the return statement at the top (again, limited by the batch separators)

  3. Use a connection based approach, which will ensure non-execution for the entire script (entire connection to be more accurate) - use something like a 'SET PARSEONLY ON' or 'SET NOEXEC ON' at the top of the script. This will ensure all statements in the connection (or until said set statement is turned off) will not execute and will instead be parsed/compiled only.

  4. Use a comment block to comment out the entire script (i.e. /* and */)

EDIT: Demonstration that the 'return' statement is batch specific - note that you will continue to see result-sets after the returns:

select 1
return
go
select 2
return
select 3
go
select 4
return
select 5
select 6
go
情定在深秋 2024-08-23 21:30:08

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

PRINT 'INACTIVE SCRIPT'
RETURN

Why not simply add the following to the beginning of the script

PRINT 'INACTIVE SCRIPT'
RETURN
旧话新听 2024-08-23 21:30:08

要解决 RETURN/GO 问题,您可以将 RAISERROR ('Oi! Stop!', 20, 1) WITH LOG 放在顶部。

这将按照 MSDN 上的 RAISERROR 关闭客户端连接。

最大的缺点是您必须是系统管理员才能使用严重性 20。

编辑:

一个简单的演示来反驳 Jersey Dude 的评论...

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

To work around the RETURN/GO issue you could put RAISERROR ('Oi! Stop!', 20, 1) WITH LOG at the top.

This will close the client connection as per RAISERROR on MSDN.

The very big downside is you have to be sysadmin to use severity 20.

Edit:

A simple demonstration to counter Jersey Dude's comment...

RAISERROR ('Oi! Stop!', 20, 1)  WITH LOG
SELECT 'Will not run'
GO
SELECT 'Will not run'
GO
SELECT 'Will not run'
GO
蒲公英的约定 2024-08-23 21:30:08

严重性为 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;

RAISERROR with severity 20 will report as error in Event Viewer.

You can use SET PARSEONLY ON; (or NOEXEC). At the end of script use 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;
瞄了个咪的 2024-08-23 21:30:08

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

这里与每个 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

Here is a somewhat kludgy way to do it that works with GO-batches, by using a "global" variable.

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

And here is the same idea used with a transaction and a try/catch block for each GO-batch. You can try to change the various conditions and/or let it generate an error (divide by 0, see comments) to test how it behaves:

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
九公里浅绿 2024-08-23 21:30:08

尝试将其作为 TSQL 脚本运行

SELECT 1
RETURN
SELECT 2
SELECT 3

返回结束执行。

RETURN (Transact-SQL)

无条件退出查询或
程序。立即退货
完整且可以随时使用
退出过程、批处理或
语句块。声明称
follow RETURN 不执行。

Try running this as a TSQL Script

SELECT 1
RETURN
SELECT 2
SELECT 3

The return ends the execution.

RETURN (Transact-SQL)

Exits unconditionally from a query or
procedure. RETURN is immediate and
complete and can be used at any point
to exit from a procedure, batch, or
statement block. Statements that
follow RETURN are not executed.

初懵 2024-08-23 21:30:08

尽管它的描述非常明确和有力,但 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 没有中断执行!

Despite its very explicit and forceful description, RETURN did not work for me inside a stored procedure (to skip further execution). I had to modify the condition logic. Happens on both 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

had to be changed into:

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

Discovered as a result of finding duplicated rows. Debugging PRINTs confirmed that @idSess had value greater than zero in the IF check - RETURN did not break execution!

客…行舟 2024-08-23 21:30:08

我知道这个问题很老了,并且以几种不同的方式得到了正确的回答,但没有像我在类似情况下使用过的答案。
第一种方法(非常基本):

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'

您可以自己轻松测试它,以确保它的行为符合预期。

I know the question is old and was answered correctly in few different ways but there is no answer as mine which I have used in similar situations.
First approach (very basic):

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

Second approach:

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

You can test it easily by yourself to make sure it behave as expected.

凤舞天涯 2024-08-23 21:30:08

当你想停止执行时,只需使用 SET NOEXEC ON 即可。

 Go
 Select 'I want to kill the job after some error or based on some validation.
 Go
 Select 'Raiserror not working'
  Go
 Select 'I have to be admin to define severity 20'
 go
Select 'I got an error, come custom validation failed, I don't want to run the 
 rest  of the script'.
Go
 SET NOEXEC ON
 Select 'rest of the script should not run after NOEXEC on executed'.

just use SET NOEXEC ON when you want to stop execution.

 Go
 Select 'I want to kill the job after some error or based on some validation.
 Go
 Select 'Raiserror not working'
  Go
 Select 'I have to be admin to define severity 20'
 go
Select 'I got an error, come custom validation failed, I don't want to run the 
 rest  of the script'.
Go
 SET NOEXEC ON
 Select 'rest of the script should not run after NOEXEC on executed'.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文