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)
这既提高了错误,并返回结果集。
要立即终止脚本,我更喜欢使用RETURN
(GOTO
在大多数存在替代方案的编程圈中,通常不鼓励使用-type 构造):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
Run Code Online (Sandbox Code Playgroud)
或者使用 处理错误TRY/CATCH
,CATCH
如果严重性为 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
方法。
您可以利用该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
)。
归档时间: |
|
查看次数: |
57855 次 |
最近记录: |