Answers:
该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”未打印。
注意事项:
参考:http : //www.mydatabasesupport.com/forums/ms-sqlserver/174037-sql-server-2000-abort-whole-script.html#post761334
noexec方法
适用于GO语句的另一种方法是set noexec on
。这将导致脚本的其余部分被跳过。它不会终止连接,但是您需要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.
如果可以使用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 Managment Studio甚至在解析时间错误时都轻而易举!不过,如果您是从命令行运行它们,那很好。
我不会使用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
即使您的验证更为复杂,您也只需要将几个标志变量包括在最终检查中。
RAISERROR
,尤其是在您不知道谁将运行脚本以及具有哪些特权的情况下。
declare @i int = 0; if @i=0 begin select '1st stmt in IF block' go end else begin select 'ELSE here' end go
在SQL 2012+,您可以使用THROW。
THROW 51000, 'Stopping execution because validation failed.', 0;
PRINT 'Still Executing'; -- This doesn't execute with THROW
从MSDN:
引发异常并将执行转移到TRY ... CATCH构造的CATCH块中。如果TRY ... CATCH构造不可用,则会话结束。设置引发异常的行号和过程。严重性设置为16。
我通过事务成功扩展了noexec开/关解决方案,以全有或全无的方式运行脚本。
set noexec off
begin transaction
go
<First batch, do something here>
go
if @@error != 0 set noexec on;
<Second batch, do something here>
go
if @@error != 0 set noexec on;
<... etc>
declare @finished bit;
set @finished = 1;
SET noexec off;
IF @finished = 1
BEGIN
PRINT 'Committing changes'
COMMIT TRANSACTION
END
ELSE
BEGIN
PRINT 'Errors occured. Rolling back changes'
ROLLBACK TRANSACTION
END
显然,即使有错误并且执行被禁用,编译器也会“理解” IF中的@finished变量。但是,仅当未禁用执行时,该值才设置为1。因此,我可以很好地相应地提交或回滚事务。
IF (XACT_STATE()) <> 1 BEGIN Set NOCOUNT OFF ;THROW 525600, 'Rolling back transaction.', 1 ROLLBACK TRANSACTION; set noexec on END;
但是执行从未停止,最终我遇到了三个“回滚事务”错误。有任何想法吗?
您可以将SQL语句包装在WHILE循环中,并在需要时使用BREAK
WHILE 1 = 1
BEGIN
-- Do work here
-- If you need to stop execution then use a BREAK
BREAK; --Make sure to have this break at the end to prevent infinite loop
END
DECLARE @ST INT; SET @ST = 1; WHILE @ST = 1; BEGIN; SET @ST = 0; ...; END
更冗长,但
您可以使用GOTO语句更改执行流程:
IF @ValidationResult = 0
BEGIN
PRINT 'Validation fault.'
GOTO EndScript
END
/* our code */
EndScript:
进一步使用refinig Sglasses方法时,以上几行强制使用SQLCMD模式,如果不使用SQLCMD模式,则终止脚本,或使用:on error exit
任何错误退出以使用
CONTEXT_INFO来跟踪状态。
SET CONTEXT_INFO 0x1 --Just to make sure everything's ok
GO
--treminate the script on any error. (Requires SQLCMD mode)
:on error exit
--If not in SQLCMD mode the above line will generate an error, so the next line won't hit
SET CONTEXT_INFO 0x2
GO
--make sure to use SQLCMD mode ( :on error needs that)
IF CONTEXT_INFO()<>0x2
BEGIN
SELECT CONTEXT_INFO()
SELECT 'This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!'
RAISERROR('This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!',16,1) WITH NOWAIT
WAITFOR DELAY '02:00'; --wait for the user to read the message, and terminate the script manually
END
GO
----------------------------------------------------------------------------------
----THE ACTUAL SCRIPT BEGINS HERE-------------
这是存储过程吗?如果是这样,我想你可以做一个Return,例如“ Return NULL”;
我建议您将适当的代码块包装在try catch块中。然后,您可以使用严重性为11的Raiserror事件,以便根据需要中断到catch块。如果您只想提高筹码,但继续在try块中执行,则使用较低的严重性。
合理?
干杯,约翰
[经编辑以包含BOL参考]
http://msdn.microsoft.com/zh-CN/library/ms175976(SQL.90).aspx
您可以使用RAISERROR。
这些都不与'GO'语句一起使用。在此代码中,无论严重性是10还是11,您都将获得最终的PRINT语句。
测试脚本:
-- =================================
PRINT 'Start Test 1 - RAISERROR'
IF 1 = 1 BEGIN
RAISERROR('Error 1, level 11', 11, 1)
RETURN
END
IF 1 = 1 BEGIN
RAISERROR('Error 2, level 11', 11, 1)
RETURN
END
GO
PRINT 'Test 1 - After GO'
GO
-- =================================
PRINT 'Start Test 2 - Try/Catch'
BEGIN TRY
SELECT (1 / 0) AS CauseError
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage
RAISERROR('Error in TRY, level 11', 11, 1)
RETURN
END CATCH
GO
PRINT 'Test 2 - After GO'
GO
结果:
Start Test 1 - RAISERROR
Msg 50000, Level 11, State 1, Line 5
Error 1, level 11
Test 1 - After GO
Start Test 2 - Try/Catch
CauseError
-----------
ErrorMessage
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Divide by zero error encountered.
Msg 50000, Level 11, State 1, Line 10
Error in TRY, level 11
Test 2 - After GO
进行此工作的唯一方法是编写不带GO
语句的脚本。有时候那很容易。有时候很难。(使用类似的东西IF @error <> 0 BEGIN ...
。)
我一直RETURN
在这里使用脚本或Stored Procedure
ROLLBACK
如果一笔交易,请确保交易成功,否则RETURN
立即导致未提交的未平仓交易
这是我的解决方案:
...
BEGIN
raiserror('Invalid database', 15, 10)
rollback transaction
return
END
您可以使用GOTO语句。尝试这个。这对您已经用光了。
WHILE(@N <= @Count)
BEGIN
GOTO FinalStateMent;
END
FinalStatement:
Select @CoumnName from TableName
谢谢你的答案!
raiserror()
可以正常工作,但您不应忘记该return
语句,否则脚本将继续运行而不会出错!(因此,raiserror不是“ throwerror” ;-)),当然,如果需要,可以进行回滚!
raiserror()
很高兴告诉执行脚本的人出了点问题。
如果您只是在Management Studio中执行脚本,并且想在出现第一个错误时停止执行或回滚事务(如果使用),那么我认为最好的方法是使用try catch块(从SQL 2005开始)。如果您正在执行脚本文件,这在Management Studio中效果很好。存储的proc也可以始终使用它。