SQL Server:クエリアナライザーに一連のバッチを中止する方法は?
-
06-09-2019 - |
質問
特別なクエリアナライザーバッチセパレーターキーワードで区切られた一連のT-SQLステートメントがあります。
GO
1つのバッチが失敗した場合、後続のバッチを試しないようにクエリアナライザーが必要です。一連のバッチの処理を停止する必要があります。
例えば:
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
解決
これが私がそれをする方法です:
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をコンパイルするだけで実際に実行しない状態です。実行(F5)の代わりに、誤って解析ツールバーボタン(CTRL+F5)を押すことに似ています。
スクリプトの最後にNOEXECをオフにすることを忘れないでください。それ以外の場合は、ユーザーは永続的な「コマンドが正常に完了した」と混乱します。メッセージ。
トライキャッチブロックを使用する代わりに、後続のバッチで@@エラーに対するチェックを使用します。次のバッチで@@エラーを使用すると、「テーブルは存在しない」などのコンパイルエラーがキャッチされます。
NOEXECモードに加えて、NoCountモードも切り替えます。 NOEXECモードをオンにしてオフにした場合、クエリは引き続きメッセージ「(0行の影響を受けた)」というメッセージを報告します。メッセージは、NOEXECモードにあるため、常にゼロ行を報告します。ただし、nocountを回すとこれらのメッセージが抑制されます。
また、SQL Server 2005を実行している場合、スキップしているコマンドが存在しないテーブルとバッチの最初のコマンドの場合はコマンドを参照する場合、エラーメッセージが表示される場合があります。コマンドを偽の印刷ステートメントでバッチ内の2番目のコマンドにすることを強制することで、これを抑制できます。見る MSバグ#569263 詳細については。
他のヒント
「クエリ、SQLCMDモード」メニューオプションをアクティブにして、スクリプトの先頭に次のことを配置できます。
:on error exit
これにより、後続のバッチがある場合でも、エラーが発生したときに実行が停止します。
エラーが無視されている典型的な動作が得られるため、sqlcmdモードをオンにしないと、誤ってスクリプトを実行しないようにしてください。
これを行う必要があるとき、私は重大度20のレイゼローを発行します。はい、それは厄介ですが、それは仕事をします。
一時テーブルを作成します。各ステップの後に更新します(成功した場合)。そして、テーブルに対して検証して、前のステップの成功を確認します。
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 ...
@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
Microsoft.public.sqlserver.programmingグループのErland sommarskogは非常に良いアイデアを持っていました。
投稿したような変更スクリプトでは、防御的である必要があり、@@ trancount> 0の場合は各バッチを開始する必要があります。
使用
IF @@trancount > 0
もっときれいです。