有没有一种方法,以立即停止执行的一个SQL脚本SQL服务器,就像一个"突破"或"退出"的命令?

我有一个剧本,一些验证和查找它开始之前做的插入的,我希望它停止,如果任何验证或查找失败。

有帮助吗?

解决方案

raiserror 方法

raiserror('Oh no a fatal error', 20, -1) with log

这将终止连接,从而停止脚本的其余部分运行。

注意,这两个严重级别的20或更高, WITH LOG 选择是必要的,它以这种方式工作。

这甚至适用于好的陈述,例如。

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'不打印。

注意事项:

  • 这只是工作,如果你登录作为管理员('系统管理员的角色),而且还让你没有数据库连接。
  • 如果你是不是记录在作为管理员,RAISEERROR()称自己会失败 和剧本将继续执行.
  • 当调用sqlcmd.exe退出的代码2745会的报告。

参考: http://www.mydatabasesupport.com/forums/ms-sqlserver/174037-sql-server-2000-abort-whole-script.html#post761334

该noexec方法

另一种方法,工作与去发言 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.

其他提示

只需使用一个RETURN(它将工作的内部和存储的过程之外)。

如果可以使用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模式没有打开,你会得到解析错误有关结肠。 Unfortuantely,仿佛运行脚本这不是一个完全防弹没有SQLCMD模式中,SQL枭雄工作室微风右过去甚至解析时错误!不过,如果你在命令行中运行它们,这是好的。

我不会用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

即使你的验证是比较复杂的,你应该只需要几个标志变量在最终检查(S),包括

我成功地扩展开/关溶液使用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,只有在执行未禁用。因此,我可以很好地提交或相应地回滚事务。

您可以换你的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

在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。

这是一个存储过程?如果是这样,我认为你可以只是做一个回报,比如“返回NULL”;

此外refinig Sglasses方法中,上述线强制使用SQLCMD模式的,并且或者treminates的scirpt如果不使用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-------------

我建议你换你适当的代码块在try catch块。您可以依次用11严重性然后使用RAISERROR事件,如果你想打破到catch块。如果你只是想raiserrors而是继续在try块内执行,然后使用较低的严重性。

请感?

干杯, 约翰

[编辑,包括BOL参考

http://msdn.microsoft.com/en -us /库/ ms175976(SQL.90)的.aspx

可以使用 GOTO语句改变执行的流程:

IF @ValidationResult = 0
BEGIN
    PRINT 'Validation fault.'
    GOTO EndScript
END

/* our code */

EndScript:

可以使用 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 ...。)

这是我的解决方案:

...

BEGIN
    raiserror('Invalid database', 15, 10)
    rollback transaction
    return
END

您可以使用GOTO语句。尝试这个。这是使用全给你。

WHILE(@N <= @Count)
BEGIN
    GOTO FinalStateMent;
END

FinalStatement:
     Select @CoumnName from TableName

我用RETURN这里所有的时间,工作在脚本或Stored Procedure

请确保您ROLLBACK交易,如果你是在一个,否则立即RETURN会造成一个开放的未提交的事务。

THX的回答!

raiserror()工作正常,但你不应该忘记return声明,否则脚本将继续没有错误! (hense的RAISERROR不是“throwerror” ;-))和如果必要的话,当然执行回滚!

raiserror()是好的,告诉谁执行出现了错误的脚本的人。

如果你只是执行Management Studio中的脚本,并希望在第一个错误停止执行或回滚事务(如果使用),那么我认为最好的方法是使用try catch块(SQL 2005年以后)。 这种运作良好,在Management Studio中,如果您正在执行一个脚本文件。 存储过程总是可以使用这一点。

早在一天,我们采用了以下...最好的工作:

RAISERROR ('Error! Connection dead', 20, 127) WITH LOG
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top