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

问题描述 投票:0回答:11

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

sql sql-server t-sql sql-scripts
11个回答
67
投票

另一种解决方案可能是使用

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 脚本中的流程控制


42
投票

不,没有 - 您有几种选择:

  1. 将整个脚本包装在一个大的 if/end 块中,只是确保它不为真(即“if 1=2 begin” - 这只有在脚本不包含任何 GO 语句时才有效(正如那些指示的那样)新一批)

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

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

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

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

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

22
投票

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

PRINT 'INACTIVE SCRIPT'
RETURN

19
投票

要解决 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
    

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

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

4
投票
尝试将其作为 TSQL 脚本运行

SELECT 1 RETURN SELECT 2 SELECT 3
返回结束执行。

返回 (Transact-SQL)

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


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


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

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'
您可以自己轻松测试它,以确保其行为符合预期。


1
投票
当你想停止执行时,只需使用 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'.
    

0
投票
古老但有用的帖子,突然停止执行的另一个选项是使用“THROW”。例如,您可以执行如下操作:

IF @@servername != 'your_server_name' THROW 51000, 'Oops, wrong server!!!', 1;

IF (GETDATE() > @TIMEOUT) THROW 52000, 'Replication checking timeout.', 1;
注意:根据 Microsoft 的建议,“THROW”将取代“RAISERROR”。

HTH.

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.