是否有一种方法可以立即停止SQL服务器中SQL脚本的执行,如“break”或“exit”命令?
我有一个脚本,它在开始插入之前执行一些验证和查找,我希望它在任何验证或查找失败时停止。
是否有一种方法可以立即停止SQL服务器中SQL脚本的执行,如“break”或“exit”命令?
我有一个脚本,它在开始插入之前执行一些验证和查找,我希望它在任何验证或查找失败时停止。
当前回答
非常感谢这里的其他人以及我读过的其他帖子。 但没有什么能满足我所有的需求,直到@jaraics回答。
我所见过的大多数答案都忽略了具有多个批处理的脚本。他们忽略了SSMS和SQLCMD的双重用法。我的脚本在SSMS中是完全可运行的——但我想要F5预防,这样他们就不会在意外中删除现有的对象集。
SET PARSEONLY ON工作得很好,可以防止不必要的F5。但是你不能用SQLCMD运行。
另一件让我慢下来的事情是Batch在出现错误时如何跳过任何进一步的命令-所以我的SET NOCOUNT ON被跳过,因此脚本仍然运行。
不管怎样,我稍微修改了一下jaraics的答案:(在这种情况下,我还需要一个数据库从命令行激活)
-----------------------------------------------------------------------
-- Prevent accidental F5
-- Options:
-- 1) Highlight everything below here to run
-- 2) Disable this safety guard
-- 3) or use SQLCMD
-----------------------------------------------------------------------
set NOEXEC OFF -- Reset in case it got stuck ON
set CONTEXT_INFO 0x1 -- A 'variable' that can pass batch boundaries
GO -- important !
if $(SQLCMDDBNAME) is not null
set CONTEXT_INFO 0x2 -- If above line worked, we're in SQLCMD mode
GO -- important !
if CONTEXT_INFO()<>0x2
begin
select 'F5 Pressed accidentally.'
SET NOEXEC ON -- skip rest of script
END
GO -- important !
-----------------------------------------------------------------------
< rest of script . . . . . >
GO
SET NOEXEC OFF
print 'DONE'
其他回答
我不会使用RAISERROR- SQL有IF语句可以用于此目的。执行您的验证和查找并设置局部变量,然后使用IF语句中的变量值使插入具有条件。
您不需要检查每个验证测试的变量结果。你通常可以用一个标志变量来确认所有传递的条件:
declare @valid bit
set @valid = 1
if -- Condition(s)
begin
print 'Condition(s) failed.'
set @valid = 0
end
-- Additional validation with similar structure
-- Final check that validation passed
if @valid = 1
begin
print 'Validation succeeded.'
-- Do work
end
即使您的验证更复杂,您也应该只需要在最终检查中包含几个标志变量。
如果你可以使用SQLCMD模式,那么咒语
:on error exit
(包括冒号)将导致RAISERROR实际停止脚本。例如,
:on error exit
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SOMETABLE]') AND type in (N'U'))
RaisError ('This is not a Valid Instance Database', 15, 10)
GO
print 'Keep Working'
将输出:
Msg 50000, Level 15, State 10, Line 3
This is not a Valid Instance Database
** An error was encountered during execution of batch. Exiting.
批次就会停止。如果SQLCMD模式未打开,则会得到关于冒号的解析错误。不幸的是,如果脚本没有在SQLCMD模式下运行,那么它并不是完全防弹的,SQL management Studio甚至可以轻松地跳过解析时间错误!不过,如果您从命令行运行它们,这是没问题的。
将它包含在try catch块中,然后执行将被转移到catch。
BEGIN TRY
PRINT 'This will be printed'
RAISERROR ('Custom Exception', 16, 1);
PRINT 'This will not be printed'
END TRY
BEGIN CATCH
PRINT 'This will be printed 2nd'
END CATCH;
raiserror方法
raiserror('Oh no a fatal error', 20, -1) with log
这将终止连接,从而停止脚本的其余部分的运行。
注意,要以这种方式工作,严重级别20或更高级别和WITH LOG选项都是必需的。
这甚至适用于GO语句,例如。
print 'hi'
go
raiserror('Oh no a fatal error', 20, -1) with log
go
print 'ho'
将给你输出:
hi
Msg 2745, Level 16, State 2, Line 1
Process ID 51 has raised user error 50000, severity 20. SQL Server is terminating this process.
Msg 50000, Level 20, State 1, Line 1
Oh no a fatal error
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command. The results, if any, should be discarded.
注意没有打印'ho'。
警告:
这只在您以admin ('sysadmin'角色)身份登录时有效,并且没有数据库连接。 如果您不是以管理员身份登录,则RAISEERROR()调用本身将失败,脚本将继续执行。 当使用sqlcmd.exe调用时,将报告退出代码2745。
参考:http://www.mydatabasesupport.com/forums/ms - sqlserver/174037 - sql - server - 2000 -中止整个script.html # post761334
noexec方法
另一个使用GO语句的方法是set noexec on (docs)。这将导致跳过脚本的其余部分。它不会终止连接,但在执行任何命令之前,您需要再次关闭noexec。
例子:
print 'hi'
go
print 'Fatal error, script will not continue!'
set noexec on
print 'ho'
go
-- last line of the script
set noexec off -- Turn execution back on; only needed in SSMS, so as to be able
-- to run this script again in the same session.
你可以使用GOTO语句改变执行流程:
IF @ValidationResult = 0
BEGIN
PRINT 'Validation fault.'
GOTO EndScript
END
/* our code */
EndScript: