2015-12-09 3 views
6

SQL TransactionGOのステートメントを複数回使用できますか?私は長いT-SQLスクリプトを持っており、SQL Transactionで実行したいと思っています。すべてがうまくいくなら、私はそうでなければロールバックすることを約束します。SQL Transactionで 'GO'を複数回使用できますか?

しかし、このクエリを実行しているうちに、'create function must be the only statement in the batch'のようなエラーが発生しました。私はその中で多くの関数と手続きを作成し、削除しています。

私はGOをスクリプト内のどこにも使用していません。私の質問は - その長いスクリプトで複数回GOステートメントを使用できますか? GOはバッチを作成し、バッチが最初に正常に実行されたが次回に失敗した場合、rollback transactionステートメントは実際に実行されたロールバックを実行できますか?

PRINT 'Transaction Started' 
BEGIN TRY 
    BEGIN TRAN 

    Drop Function 
    .... 
    .... 
    Create Function 
    .... 
    .... 
    Drop Procedure 
    .... 
    .... 
    Lots of statements 
    .... 
    .... 

    COMMIT TRAN 
    PRINT 'Transaction Succeeded' 
END TRY 
BEGIN CATCH 
    PRINT 'Transaction Failed' 
    IF(@@TRANCOUNT > 0) 
     ROLLBACK TRAN 
END CATCH 

私は単一のスクリプトでNEWDBからoldDBにいくつかの変更を移行するには、このスクリプトを作成しています:私のスクリプトの

構造は次のようになります。

+0

このスクリプトでは、ストアド・プロシージャまたは関数を作成していますか? – Dane

+0

私は自分の答えを更新しました。とにかく..私は両方を作成しています。最初にそれらが存在するかどうかをチェックする。 –

+0

ここでこの答えを試してください:http://stackoverflow.com/a/11121382/249813 – JamesT

答えて

16

あなたはコンセプトをミックスしています。 GOはTransact-SQLの概念ではなく、言語の一部ではなく、SQL Serverでは認識されません。 GOはツールバッチ区切り文字です。 sqlcmd.exeとSSMSはどちらもバッチ区切り文字としてデフォルトでGOを使用しています。バッチ区切り記号は、個のバッチをSQLソースファイル内のを識別するために使用します。クライアントツールは、一度に1つのバッチをサーバーに送信します(もちろん、区切り文字は省略します)。

トランザクションはバッチにまたがることができます。 TRY/CATCHブロックはできません。 CREATE/ALTERステートメントはバッチ内の唯一のステートメントでなければなりません(コメントはステートメントではなく、関数プロシージャー本体に含まれるステートメントも含まれています)。

トランザクションを開始し、最初のエラー(-bsqlcmd.exeの開始時、または:on error exit in SSMSを使用)で実行を中止することで、似たようなことを実現できます。

しかし、長いトランザクションでDDLを実行することはできません。特に、DMLと混在させる予定がある場合は特にそうです。 ほとんどの私が調査しなければならなかった破損は、この組み合わせ(Xact、DDL + DML、ロールバック)に由来します。私はそれを強く勧めます。

スキーマの更新を安全に展開する唯一の方法は、何か問題が発生した場合にバックアップから展開、展開、復元することです。ダンは(動的SQL)を推奨しています何sp_executesqlが新しい、インナー、バッチを開始しないために動作することを

注意。このバッチはCREATE/ALTERの制限を満たします。

+0

すばらしい説明。すごい提案。おかげさまで@Remus !! –

1

GOは使いやすいキーワードです。 GOは最後のコードブロックを完了し、次のブロックに進みます。はい、ステートメント内で複数のGOを使用して複数のバッチに分割することができます。しかし、トランザクションベースのロジックを実行しているので、GOの組み合わせでtry/catchロジックを使用する方が良いでしょう。 https://msdn.microsoft.com/en-us/library/ms175976.aspxこのサイトでは、使用するためのいくつかの例を示しています。ヒッチに遭遇した場合は、そのエラーを出力し、選択した場合は続行できます。

2

GO is not a SQL keyword。これは、SQL Server Management Studioのと、他のクライアントツールによって使用されるクライアント側のバッチ区切りです。

GOはトランザクションスコープに影響しません。 BEGIN TRANは現在の接続でトランザクションを開始します。 COMMITとROLLBACKはトランザクションを終了します。その間に必要な数だけステートメントを実行できます。 GOは個別に明細書を実行します。

MSDNで指定されているように

TRY ... CATCH構造は、複数のバッチにまたがることはできません。

したがって、BEGIN TRY、END TRY、BEGIN CATCH、およびEND CATCHは、GOセパレータで別々のバッチに分割することはできません。それらは同じクエリに現れなければなりません。

あなたは、以下の不正なSQLのようなTRY/CATCH文でバッチ区切りを含めるようにしようとしない場合:

begin try 
    go 
end try 
begin catch 
    go 
end catch 

これは構文エラーを返し、3種類のクエリを実行します:

1)begin try

Msg 102, Level 15, State 1, Line 1 
Incorrect syntax near 'begin'. 

2)end try begin catch

Msg 102, Level 15, State 1, Line 3 
Incorrect syntax near 'try'. 

3)end catch

Msg 102, Level 15, State 1, Line 6 
Incorrect syntax near 'catch'. 
関連する問題