如何中断SQL脚本执行

New*_*per 18 sql-server-2005 sql-server error-handling

我正在处理 sql 脚本,如果不满足某些条件,我需要停止继续该脚本。

当我谷歌它时,我发现 20 严重级别的 RaisError 将终止它。但由于某些原因,我不能使用该选项。

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

Jon*_*gel 10

RAISERROR 文档(强调我的):

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

您正在执行脚本的主体很可能不符合这些标准。

使用没有任何问题RAISERROR; 您只是使用了过高的严重性级别。我使用级别 16 作为引发错误的默认值,序列将终止。如果想更准确,可以按照微软自己给出的等级:

在此处输入图片说明

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

例如:

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

SELECT 1;   /* Executed! */
Run Code Online (Sandbox Code Playgroud)

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

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

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

SELECT 1;   /* Not executed */
Run Code Online (Sandbox Code Playgroud)

或者使用 处理错误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
Run Code Online (Sandbox Code Playgroud)

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

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

SELECT 1;   /* Not executed */
GO

SELECT 2;   /* Executed! */
Run Code Online (Sandbox Code Playgroud)

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

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

SELECT 1;   /* Not executed */
GO

IF (@@ERROR != 0)
    RETURN;

SELECT 2;   /* Not executed */
Run Code Online (Sandbox Code Playgroud)

编辑:正如 Martin Smith 在评论中正确指出的那样,这仅适用于 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 */
Run Code Online (Sandbox Code Playgroud)

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


Tho*_*ger 8

您可以利用该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...';
Run Code Online (Sandbox Code Playgroud)

此执行的输出将如下所示:

here is the first statement...
here is the second statement...
here is the end of the script...
Run Code Online (Sandbox Code Playgroud)

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

  • 仅在有单个批次时才有效,一旦您有 GO 语句就会中断。 (7认同)