如何中断SQL脚本执行


16

我正在使用sql脚本,如果不满足某些条件,我有停止继续执行脚本的要求。

当我用Google搜索它时,我发现RaisError严重性级别为20会终止它。但是由于某些原因,我无法使用该选项。

能否请我提供停止SQL脚本执行的替代方法。


1
为什么引发错误是不可接受的?该脚本也是存储过程吗?
Namphibian

我不清楚您的拳头问题。第二个问题;不,这不是SP
新开发者

1
什么是脚本?它包含多个批次吗?您在这里看到答案了吗?
马丁·史密斯

Answers:


8

RAISERROR文档(重点是我的):

任何用户都可以指定从0到18的严重级别。只能由sysadmin固定服务器角色的成员或具有ALTER TRACE权限的用户指定从19到25的严重级别。对于19到25的严重性级别,需要WITH LOG选项。

您执行脚本的主体很可能不符合这些条件。

使用没有什么错RAISERROR;您所使用的严重性级别过高。我将级别16用作引发错误的默认值,并且该序列将终止。如果要更准确,可以遵循Microsoft本身给出的级别:

在此处输入图片说明

现在,根据脚本的上下文说了这么多话,使用RAISERROR可能还不够,因为它本身不会“退出”脚本(使用正常的严重性级别)。

例如:

RAISERROR(N'Test', 16, 1);

SELECT 1;   /* Executed! */

提高了错误,并返回结果集。

要立即终止脚本,我更喜欢使用RETURNGOTO在存在替代方案的大多数编程领域中,通常不建议使用-type构造):

RAISERROR(N'Test', 16, 1);
RETURN;

SELECT 1;   /* Not executed */

或使用来处理错误TRY/CATCHCATCH如果严重性为11或更高,将导致执行跳至该块:

BEGIN TRY
    RAISERROR(N'Test', 16, 1);
    SELECT 1;   /* Not executed */
END TRY
BEGIN CATCH
    SELECT 2;   /* Executed */
END CATCH

BEGIN TRY
    RAISERROR(N'Test', 10, 1);
    SELECT 1;   /* Executed */
END TRY
BEGIN CATCH
    SELECT 2;   /* Not executed */
END CATCH

一个单独的问题是,如果脚本跨越多个批次- RETURN将仅退出该批次

RAISERROR(N'Test', 16, 1);
RETURN;

SELECT 1;   /* Not executed */
GO

SELECT 2;   /* Executed! */

要解决此问题,您可以@@ERROR在每批开始时进行检查:

RAISERROR(N'Test', 16, 1);
RETURN;

SELECT 1;   /* Not executed */
GO

IF (@@ERROR != 0)
    RETURN;

SELECT 2;   /* Not executed */

编辑:由于马丁·史密斯正确地在注释中指出,这仅适用于2个批次。要扩展到3个或更多批次,您可以像这样级联引发错误(注意:该GOTO方法不能解决此问题,因为必须在批次中定义目标标签):

RAISERROR(N'Test', 16, 1);
RETURN;

SELECT 1;   /* Not executed */
GO

IF (@@ERROR != 0)
BEGIN
    RAISERROR(N'Error already raised. See previous errors.', 16, 1);
    RETURN;
END

SELECT 2;   /* Not executed */
GO

IF (@@ERROR != 0)
BEGIN
    RAISERROR(N'Error already raised. See previous errors.', 16, 1);
    RETURN;
END

SELECT 3;   /* Not executed */

或者,正如他还指出的那样,如果适合您的环境,则可以使用该SQLCMD方法


最后的建议不起作用。参见pastebin。我喜欢这里的sqlcmd方法
马丁·史密斯

6

您可以利用该GOTO语句在所需的任何地方跳过。换句话说,您遇到了错误或其他某种情况,并且可以在脚本底部添加一个标签(即TheEndOfTheScript:),然后发出一条goto TheEndOfTheScript;语句。

这是一个快速示例:

print 'here is the first statement...';

print 'here is the second statement...';

-- substitute whatever conditional flow determining factor
-- you'd like here. I have chosen a dummy statement that will
-- always return true
--
if (1 = 1)
    goto TheEndOfTheScript;

print 'here is the third statement...';

print 'here is the fourth statement...';


TheEndOfTheScript:
print 'here is the end of the script...';

该执行的输出如下:

here is the first statement...
here is the second statement...
here is the end of the script...

如您所见,GOTO跳过了打印第三和第四条语句,并直接跳到标签(TheEndOfTheScript)。


7
仅在有一个批处理时有效,一旦您有GO语句,它将立即中断。
加百利2015年


0

同意SET NOEXEC ON/OFF,但是在Stored Procs(包含单个块)中,我只使用RETURN语句。

注意事项:在脚本文件中,如果您有多个GO语句,RETURN它将仅从当前块中出来,并继续下一个块/批处理。

注意:GOTO应该是不好的编码习惯,TRY..CATCH建议使用“ ”,因为它是从SQL Server 2008开始引入的,随后是THROW2012年。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.