我正在使用sql脚本,如果不满足某些条件,我有停止继续执行脚本的要求。
当我用Google搜索它时,我发现RaisError严重性级别为20会终止它。但是由于某些原因,我无法使用该选项。
能否请我提供停止SQL脚本执行的替代方法。
我正在使用sql脚本,如果不满足某些条件,我有停止继续执行脚本的要求。
当我用Google搜索它时,我发现RaisError严重性级别为20会终止它。但是由于某些原因,我无法使用该选项。
能否请我提供停止SQL脚本执行的替代方法。
Answers:
从RAISERROR文档(重点是我的):
任何用户都可以指定从0到18的严重级别。只能由sysadmin固定服务器角色的成员或具有ALTER TRACE权限的用户指定从19到25的严重级别。对于19到25的严重性级别,需要WITH LOG选项。
您执行脚本的主体很可能不符合这些条件。
使用没有什么错RAISERROR
;您所使用的严重性级别过高。我将级别16用作引发错误的默认值,并且该序列将终止。如果要更准确,可以遵循Microsoft本身给出的级别:
现在,根据脚本的上下文说了这么多话,使用RAISERROR
可能还不够,因为它本身不会“退出”脚本(使用正常的严重性级别)。
例如:
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Executed! */
这既提高了错误,并返回结果集。
要立即终止脚本,我更喜欢使用RETURN
(GOTO
在存在替代方案的大多数编程领域中,通常不建议使用-type构造):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
或使用来处理错误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
一个单独的问题是,如果脚本跨越多个批次- 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
方法。
您可以利用该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
)。
最好的方法是使用SET NOEXEC ON
您可以在此处阅读更多内容:如何根据SQL SERVER中的某些条件,停止或暂停或中断执行当前语句中的语句,并在以后的语句中执行GO语句分隔的语句
同意SET NOEXEC ON/OFF
,但是在Stored Procs(包含单个块)中,我只使用RETURN
语句。
注意事项:在脚本文件中,如果您有多个GO
语句,RETURN
它将仅从当前块中出来,并继续下一个块/批处理。
注意:GOTO
应该是不好的编码习惯,TRY..CATCH
建议使用“ ”,因为它是从SQL Server 2008开始引入的,随后是THROW
2012年。