SQL Server:如何中止查询分析器中的一系列批处理?
我有一系列由特殊查询分析器批次分隔符关键字分隔的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我的做法如下:
“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:
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.
您可以激活“查询,SQLCMD 模式”菜单选项并将以下内容放在脚本的开头:
这将在发生错误时停止执行,即使有后续批次也是如此。
只需确保您不会在没有打开 SQLCMD 模式的情况下意外运行脚本,因为您将得到忽略错误的典型行为。
You can activate the "Query, SQLCMD Mode" menu option and place the following at the beginning of the script:
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.
当我需要执行此操作时,我会发出严重级别为 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.
创建临时表; 并在每个步骤后更新它(如果成功); 然后通过对照表进行验证来检查上一步是否成功。
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.
基于@u07ch的想法,但仅在失败时插入...
输出2000:
输出2005/2008:
based on @u07ch idea, but only insert on failure...
output 2000:
output 2005/2008:
microsoft.public.sqlserver.programming 小组的 Erland Sommarskog 有一个非常好的主意:
使用起来
更加干净。
Erland Sommarskog in the microsoft.public.sqlserver.programming group had a very good idea:
Using
is much cleaner.