5

我有一系列由特殊查询分析器批处理分隔符关键字分隔的 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
4

6 回答 6

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

“noexec”模式使 SSMS 处于一种仅编译 T-SQL 而实际上并不执行它的状态。这类似于意外按下 Parse 工具栏按钮 (Ctrl+F5) 而不是 Execute (F5)。

不要忘记在脚本末尾关闭 noexec。否则用户会被永久的“命令成功完成”弄糊涂。消息。

我在后续批次中使用了对 @@error 的检查,而不是使用 TRY CATCH 块。在下一批中使用@@error 将捕获编译错误,例如“表不存在”。

除了 noexec 模式,我还切换了 nocount 模式。在 noexec 模式打开和 nocount 关闭的情况下,您的查询仍将报告消息“(0 行受影响)”。该消息始终报告零行,因为您处于 noexec 模式。但是,打开 nocount 会抑制这些消息。

另请注意,如果运行 SQL Server 2005,如果您正在跳过的命令引用一个不存在的表,并且如果该命令引用批处理中的第一个命令,则它可能仍会给出错误消息。使用伪造的 Print 语句强制命令成为批处理中的第二个命令可以抑制这种情况。有关详细信息,请参阅MS 错误 #569263

于 2012-05-23T06:46:52.757 回答
4

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

:on error exit

这将在发生错误时停止执行,即使有后续批次也是如此。

只要确保您不会在没有开启 SQLCMD 模式的情况下意外运行脚本,因为您将获得忽略错误的典型行为。

于 2009-10-13T02:41:39.913 回答
2

当我需要执行此操作时,我会发出严重性为 20 的 RAISERROR。这将终止当前连接,并阻止后续的“GO 批处理”执行。是的,这可能很尴尬,但它确实有效。

于 2009-10-13T02:52:45.430 回答
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 ...
于 2009-05-29T17:15:53.800 回答
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
于 2009-05-29T17:32:08.040 回答
0

microsoft.public.sqlserver.programming 组中的 Erland Sommarskog 有一个非常好的主意:

在您发布的更改脚本中,您需要采取防御措施,并以 IF @@trancount > 0 开始每个批次。

使用

IF @@trancount > 0 

干净多了。

于 2009-06-03T18:13:51.617 回答