Microsoft SQL Server T-SQL 中是否有命令告诉脚本停止处理? 我有一个脚本想要保留用于存档目的,但我不希望任何人运行它。
另一种解决方案可能是使用
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 脚本中的流程控制。
不,没有 - 您有几种选择:
将整个脚本包装在一个大的 if/end 块中,只是确保它不为真(即“if 1=2 begin” - 这只有在脚本不包含任何 GO 语句时才有效(正如那些指示的那样)新一批)
使用顶部的 return 语句(同样,受批次分隔符的限制)
使用基于连接的方法,这将确保整个脚本不执行(整个连接更准确) - 在顶部使用类似 'SET PARSEONLY ON' 或 'SET NOEXEC ON' 的内容脚本。这将确保连接中的所有语句(或直到关闭所述 set 语句)都不会执行,而只会被解析/编译。
使用注释块注释掉整个脚本(即/*和*/)
编辑:演示“返回”语句是特定于批次的 - 请注意,您将在返回后继续看到结果集:
select 1
return
go
select 2
return
select 3
go
select 4
return
select 5
select 6
go
为什么不简单地将以下内容添加到脚本的开头
PRINT 'INACTIVE SCRIPT'
RETURN
要解决 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
可以使用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;
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
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 没有中断执行!
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'
您可以自己轻松测试它,以确保其行为符合预期。
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'.
IF @@servername != 'your_server_name'
THROW 51000, 'Oops, wrong server!!!', 1;
或
IF (GETDATE() > @TIMEOUT)
THROW 52000, 'Replication checking timeout.', 1;
注意:根据 Microsoft 的建议,“THROW”将取代“RAISERROR”。HTH.