web-dev-qa-db-ja.com

SQL Server - SQLスクリプトの実行を停止または中断します。

"break"または "exit"コマンドのように、SQLサーバーでSQLスクリプトの実行を即座に停止する方法はありますか?

挿入を開始する前に検証と検索を行うスクリプトがあります。検証または検索のいずれかが失敗した場合は、スクリプトを停止させます。

296
Andy White

raiserror メソッド

raiserror('Oh no a fatal error', 20, -1) with log

これにより接続が終了し、それによってスクリプトの残りの部分の実行が停止します。

この方法で動作させるには、重大度レベル20以上とWITH LOGオプションの両方が必要です。

これはGOステートメントでも動作します。

print 'hi'
go
raiserror('Oh no a fatal error', 20, -1) with log
go
print 'ho'

あなたに出力を与えるでしょう:

hi
Msg 2745, Level 16, State 2, Line 1
Process ID 51 has raised user error 50000, severity 20. SQL Server is terminating this process.
Msg 50000, Level 20, State 1, Line 1
Oh no a fatal error
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command.  The results, if any, should be discarded.

'ho'が印刷されていないことに注意してください。

警告:

  • これはadmin( 'sysadmin'ロール)としてログインしている場合にのみ機能し、またデータベースに接続していない状態になります。
  • 管理者としてログインしていない場合、RAISEERROR()呼び出し自体は失敗し、スクリプトは引き続き実行されます
  • Sqlcmd.exeで呼び出されると、終了コード2745が報告されます。

参照: http://www.mydatabasesupport.com/forums/ms-sqlserver/174037-sql-server-2000-abort-whole-script.html#post761334

noexecメソッド

GOステートメントを扱うもう一つの方法はset noexec onです。これにより、残りのスクリプトはスキップされます。接続は切断されませんが、コマンドを実行する前にnoexecを再びオフにする必要があります。

例:

print 'hi'
go

print 'Fatal error, script will not continue!'
set noexec on

print 'ho'
go

-- last line of the script
set noexec off -- Turn execution back on; only needed in SSMS, so as to be able 
               -- to run this script again in the same session.
339
Blorgbeard

RETURNを使用するだけです(ストアドプロシージャの内側と外側の両方で機能します)。

170
Gordon Bell

あなたがSQLCMDモードを使用することができるならば、呪文

:on error exit

(コロンを含めると)RAISERRORは実際にスクリプトを停止します。例えば。、

:on error exit

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SOMETABLE]') AND type in (N'U')) 
    RaisError ('This is not a Valid Instance Database', 15, 10)
GO

print 'Keep Working'

出力されます:

Msg 50000, Level 15, State 10, Line 3
This is not a Valid Instance Database
** An error was encountered during execution of batch. Exiting.

そしてバッチは停止します。 SQLCMDモードがオンになっていない場合は、コロンに関する解析エラーが発生します。残念ながら、スクリプトがSQLCMDモードになっていない状態で実行されているように、SQL Managment Studioが解析エラーを過ぎてもすぐに表示されるので、完璧ではありません。それでも、コマンドラインから実行しているのであれば、これで問題ありません。

47
Sglasses

私はRAISERRORを使用しません。SQLにはこの目的に使用できるIFステートメントがあります。検証と検索を行い、ローカル変数を設定してから、IFステートメントで変数の値を使用して、挿入を条件付きにします。

あなたはすべての検証テストの変数の結果をチェックする必要はないでしょう。渡されたすべての条件を確認するために、通常はこれを1つのフラグ変数だけで実行できます。

declare @valid bit

set @valid = 1

if -- Condition(s)
begin
  print 'Condition(s) failed.'
  set @valid = 0
end

-- Additional validation with similar structure

-- Final check that validation passed
if @valid = 1
begin
  print 'Validation succeeded.'

  -- Do work
end

検証がもっと複​​雑な場合でも、最終チェックに含めるためのフラグ変数がいくつかあれば十分です。

21
Dave Swersky

私はnoexec on/offソリューションをトランザクションでうまく拡張して、スクリプトをall or nothingで実行しました。

set noexec off

begin transaction
go

<First batch, do something here>
go
if @@error != 0 set noexec on;

<Second batch, do something here>
go
if @@error != 0 set noexec on;

<... etc>

declare @finished bit;
set @finished = 1;

SET noexec off;

IF @finished = 1
BEGIN
    PRINT 'Committing changes'
    COMMIT TRANSACTION
END
ELSE
BEGIN
    PRINT 'Errors occured. Rolling back changes'
    ROLLBACK TRANSACTION
END

エラーが発生して実行が無効になっていても、コンパイラはIF内の@finished変数を「理解」しているようです。ただし、値が1に設定されているのは、実行が無効にされていない場合だけです。したがって、トランザクションを適切にコミットまたはロールバックできます。

13
Tz_

SQL 2012以降では、 THROW を使用できます。

THROW 51000, 'Stopping execution because validation failed.', 0;
PRINT 'Still Executing'; -- This doesn't execute with THROW

MSDNから:

例外を発生させて、TRY…CATCH構文のCATCHブロックに実行を移します... TRY…CATCH構文が利用できない場合、セッションは終了します。例外が発生した行番号と手続きが設定されます。重大度は16に設定されています。

12
Jordan Parker

sQL文をWHILEループでラップし、必要に応じてBREAKを使用することができます。

WHILE 1 = 1
BEGIN
   -- Do work here
   -- If you need to stop execution then use a BREAK


    BREAK; --Make sure to have this break at the end to prevent infinite loop
END
12
Jon Erickson

これはストアドプロシージャですか?もしそうなら、私はあなたが "Return NULL"のようなただReturnをすることができると思います。

8
mtazva

Sglassesメソッドをさらに洗練し、上記の行はSQLCMDモードの使用を強制し、SQLCMDモードを使用しない場合はscirptを終了させるか、エラーが発生した場合は:on error exitを使用して終了
CONTEXT_INFO は状態を追跡するために使用されます。

SET CONTEXT_INFO  0x1 --Just to make sure everything's ok
GO 
--treminate the script on any error. (Requires SQLCMD mode)
:on error exit 
--If not in SQLCMD mode the above line will generate an error, so the next line won't hit
SET CONTEXT_INFO 0x2
GO
--make sure to use SQLCMD mode ( :on error needs that)
IF CONTEXT_INFO()<>0x2 
BEGIN
    SELECT CONTEXT_INFO()
    SELECT 'This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!'
    RAISERROR('This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!',16,1) WITH NOWAIT 
    WAITFOR DELAY '02:00'; --wait for the user to read the message, and terminate the script manually
END
GO

----------------------------------------------------------------------------------
----THE ACTUAL SCRIPT BEGINS HERE-------------
8
jaraics

適切なコードブロックをtry catchブロックで囲むことをお勧めします。あなたが望むならそれからcatchブロックに割り込むために11の重大度でRaiserrorイベントを使うことができます。単に昇格させたいがtryブロック内で実行を続けたい場合は、より低い重大度を使用してください。

理にかなって?

乾杯、ジョン

[BOL参照を含めるように編集]

http://msdn.Microsoft.com/ja-jp/library/ms175976(SQL.90).aspx

6
John Sansom

GOTO ステートメントを使用して実行の流れを変更できます。

IF @ValidationResult = 0
BEGIN
    PRINT 'Validation fault.'
    GOTO EndScript
END

/* our code */

EndScript:
6
Charlie

これらのどれも 'GO'ステートメントで動作しません。このコードでは、重大度が10か11かにかかわらず、最後のPRINTステートメントが得られます。

テストスクリプト:

-- =================================
PRINT 'Start Test 1 - RAISERROR'

IF 1 = 1 BEGIN
    RAISERROR('Error 1, level 11', 11, 1)
    RETURN
END

IF 1 = 1 BEGIN
    RAISERROR('Error 2, level 11', 11, 1)
    RETURN
END
GO

PRINT 'Test 1 - After GO'
GO

-- =================================
PRINT 'Start Test 2 - Try/Catch'

BEGIN TRY
    SELECT (1 / 0) AS CauseError
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE() AS ErrorMessage
    RAISERROR('Error in TRY, level 11', 11, 1)
    RETURN
END CATCH
GO

PRINT 'Test 2 - After GO'
GO

結果:

Start Test 1 - RAISERROR
Msg 50000, Level 11, State 1, Line 5
Error 1, level 11
Test 1 - After GO
Start Test 2 - Try/Catch
 CauseError
-----------

ErrorMessage
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Divide by zero error encountered.

Msg 50000, Level 11, State 1, Line 10
Error in TRY, level 11
Test 2 - After GO

これを機能させる唯一の方法は、GOステートメントを使わずにスクリプトを書くことです。時には簡単です。時にはそれはかなり難しいです。 (IF @error <> 0 BEGIN ...のようなものを使用してください。)

4
Rob Garrison

あなたは RAISERROR を使うことができます。

4
Mladen Prajdic

これが私の解決策でした:

...

BEGIN
    raiserror('Invalid database', 15, 10)
    rollback transaction
    return
END
3

GOTO文を使用することができます。これを試して。これはあなたのためにいっぱい使用です。

WHILE(@N <= @Count)
BEGIN
    GOTO FinalStateMent;
END

FinalStatement:
     Select @CoumnName from TableName
3
Vishal Kiri

私はここではRETURNをいつも使っています。スクリプトで動くかStored Procedure

トランザクションに参加している場合は、トランザクションをROLLBACKにします。それ以外の場合、RETURNはすぐに未確定のオープントランザクションになります。

2
jerryhung

答えはTHX!

raiserror()は正常に動作しますが、returnステートメントを忘れないでください。そうしないと、スクリプトはエラーなしで続行されます。 (raiserrorは "throwerror"ではありません;-))そしてもちろん必要ならロールバックをしてください!

raiserror()は、スクリプトを実行した人に、問題が発生したことを通知するのに最適です。

1
hfrmobile

Management Studioで単にスクリプトを実行していて、最初のエラーで実行を停止したりトランザクションをロールバックしたい場合(使用している場合)は、try catchブロックを使用するのが最善の方法です(SQL 2005以降)。スクリプトファイルを実行している場合、これはManagement Studioでうまく機能します。ストアドプロシージャは常にこれを使うことができます。

1
Bhargav Shah

当時私達は次のものを使っていました...うまくいった:

RAISERROR ('Error! Connection dead', 20, 127) WITH LOG
0
Lee