SQL Server:如何在查询分析器中中止一系列批处理?

时间:2009-05-29 17:08:58

标签: sql-server sql-server-2005 sql-server-2000 query-analyzer

我有一系列由特殊查询分析器批处理分隔符关键字分隔的T-SQL语句:

GO

如果一个批次失败,我需要查询分析器不尝试后续批次 - 我希望它停止处理一系列批次。

例如:

PRINT 'This runs'
go

SELECT 0/0, 'This causes an error'
go

PRINT 'This should not run'
go

输出:

This runs
Server: Msg 8134, Level 16, State 1, Line 2
Divide by zero error encountered.
This should not run

可能的?


更新

实际使用中的一个例子可能是:

 sp_rename 'Shelby', 'Kirsten'
 go

 DROP VIEW PeekAView
 go

 CREATE VIEW PeekAViewAS 
 SELECT * FROM Kirsten
 go

6 个答案:

答案 0 :(得分:8)

以下是我的表现:

PRINT 'This runs'
go

SELECT 0/0, 'This causes an error'
go
if (@@error <> 0)
    Begin
    set nocount on
    set noexec on
    End
GO

PRINT 'This should not run'
go

set noexec off
set nocount off
GO

&#34; noexec&#34;模式放置SSMS是一种只编译T-SQL并且实际上不执行它的状态。它类似于意外按下Parse工具栏按钮(Ctrl + F5)而不是Execute(F5)。

不要忘记在脚本结束时关闭noexec。否则,用户将会被永久性的&#34;命令成功完成混淆。&#34;消息。

我在后续批次中使用对@@ error的检查,而不是使用TRY CATCH块。在下一批中使用@@ error会捕获编译错误,例如&#34;表格不存在&#34;。

除了noexec模式,我还切换了nocount模式。启用noexec模式并关闭nocount后,您的查询仍将报告消息&#34;(0行(s)受影响)&#34;。该消息始终报告零行,因为您处于noexec模式。但是,转换nocount会抑制这些消息。

另请注意,如果运行SQL Server 2005,则跳过的命令如果引用了不存在的表,则可能仍会显示错误消息,如果批处理中的第一个命令,则该命令仍然是命令。使用伪造的Print语句强制命令成为批处理中的第二个命令可以抑制此操作。有关详细信息,请参阅MS Bug #569263

答案 1 :(得分:4)

您可以激活“查询,SQLCMD模式”菜单选项并将以下内容放在脚本的开头:

:on error exit

即使存在后续批次,这也会在发生错误时停止执行。

确保在没有启用SQLCMD模式的情况下不小心运行脚本,因为您将获得忽略错误的典型行为。

答案 2 :(得分:2)

当我需要这样做时,我发出一个严重级为20的RAISERROR。这个或更高级别将终止当前连接,并阻止后续的“GO批次”执行。是的,它可能很尴尬,但它可以完成这项工作。

答案 3 :(得分:1)

创建临时表;并在每个步骤后更新它(如果成功);然后通过验证表来检查上一步的成功。

create table #ScriptChecker (SuccessfullStep int)

-- Do Step One
Insert into #ScriptChecker
Select 1

-- Step 2
If exists (select * from #ScriptChecker where SuccessfullStep = 1)
-- Do Step 2 ...

答案 4 :(得分:1)

基于@ u07ch的想法,但只在失败时插入......

create table #test (failure  int)

if not exists (select * from #test)
BEGIN
    print 'one' --sql here
END
go

if not exists (select * from #test)
BEGIN
    print 'two'--sql here
END
go

if not exists (select * from #test)
BEGIN
    print 'three' ---SQL SERVER 2000 version
    --error--
    SELECT 0/0, 'This causes an error'
    IF @@ERROR!=0
    BEGIN
        insert into #test values (1)
        PRINT 'ERROR'
    END
end 
go

if not exists (select * from #test)
BEGIN
    print 'three'  ---SQL SERVER 2005/2008 version
    BEGIN TRY
    --error--
        SELECT 0/0, 'This causes an error'
    END TRY
    BEGIN CATCH
        insert into #test values (1)
        PRINT 'ERROR'
    END CATCH
END
go

if not exists (select * from #test)
BEGIN
    --sql here
    print 'four'
END
go

输出2000:

one
two
three

----------- --------------------
Msg 8134, Level 16, State 1, Line 7
Divide by zero error encountered.

(1 row(s) affected)

ERROR

输出2005/2008:

one
two
three

----------- --------------------

(0 row(s) affected)

(1 row(s) affected)

ERROR

答案 5 :(得分:0)

microsoft.public.sqlserver.programming小组中的Erland Sommarskog有一个非常好的想法:

  

在诸如你之类的改变脚本中   张贴,你需要防守,并且   使用IF @@ trancount&gt;开始每批次   0

使用

IF @@trancount > 0 

更干净。