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

发布于 2024-07-21 08:15:39 字数 598 浏览 17 评论 0原文

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

i have a series of T-SQL statements separated by the special Query Analyzer batch separator keyword:

GO

If one batch fails, i need Query Analyzer to not try subsequent batches - i want it to stop processing the series of batches.

For example:

PRINT 'This runs'
go

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

PRINT 'This should not run'
go

Output:

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

Possible?


Update

An example of this in real use might be:

 sp_rename 'Shelby', 'Kirsten'
 go

 DROP VIEW PeekAView
 go

 CREATE VIEW PeekAViewAS 
 SELECT * FROM Kirsten
 go

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

滥情哥ㄟ 2024-07-28 08:15:39

我的做法如下:

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 但并不实际执行它的状态。 这类似于意外按下“解析”工具栏按钮 (Ctrl+F5) 而不是“执行”(F5)。

不要忘记在脚本末尾关闭 noexec。 否则,用户将会对永久的“命令成功完成”感到困惑。 消息。

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

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

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

Here is how I'd do it:

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

The "noexec" mode puts SSMS is a state where it just compiles the T-SQL and doesn't actually execute it. It is similar to accidentally pressing the Parse toolbar button (Ctrl+F5) instead of Execute (F5).

Don't forget to turn noexec back off at the end of your script. Otherwise users are going to get confused by permanent "Command(s) completed successfully." messages.

I use the check against @@error in the subsequent batch instead of using TRY CATCH blocks. Using @@error in the next batch will catch compile errors, like "table doesn't exist".

In addition to the noexec mode, I also toggle the nocount mode. With noexec mode on and nocount off, your queries will still report a message "(0 rows(s) affected)". The message always reports zero rows, because you're in noexec mode. However, turning nocount on suppresses these messages.

Also note that if running SQL Server 2005 the command you are skipping might still give error messages if it references a table that doesn't exist and the command if the first command in the batch. Forcing the command to be the second command in the batch with a bogus Print statement can suppress this. See MS Bug #569263 for more details.

风吹雪碎 2024-07-28 08:15:39

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

:on error exit

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

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

You can activate the "Query, SQLCMD Mode" menu option and place the following at the beginning of the script:

:on error exit

This will stop execution when an error occurs, even if there are subsequent batches.

Just make sure that you don't accidentally run the script without SQLCMD mode on because you will get the typical behavior where errors are ignored.

淡水深流 2024-07-28 08:15:39

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

When I need to do this, I issue a RAISERROR of severity 20. This, or higher, will kill the current connection, and prevent subsequent "GO batches" from executing. Yes, it can be awkward, but it does the job.

夜深人未静 2024-07-28 08:15:39

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

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 ...

Create a temporary table; and update it after each step (if successful); and then check the success of the previous step by validating against the table.

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 ...
剩余の解释 2024-07-28 08:15:39

基于@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

based on @u07ch idea, but only insert on failure...

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

output 2000:

one
two
three

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

(1 row(s) affected)

ERROR

output 2005/2008:

one
two
three

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

(0 row(s) affected)

(1 row(s) affected)

ERROR
笔芯 2024-07-28 08:15:39

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

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

使用起来

IF @@trancount > 0 

更加干净。

Erland Sommarskog in the microsoft.public.sqlserver.programming group had a very good idea:

In a change script such as the one you
posted, you need to be defensive, and
start each batch with IF @@trancount >
0.

Using

IF @@trancount > 0 

is much cleaner.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文