すべてのSQLステートメントの後にGOステートメントを使用する理由は何ですか? GOがバッチの終了を通知し、ステートメントのレピュテーションを許可することを理解していますが、ステートメントごとにGOを使用するとどのような利点がありますか。
多くのMicrosoftのドキュメントなどがすべてのステートメントの後でそれを使い始めたので、またはおそらく気づき始めたので、私は興味があります。
また、ベストプラクティスとは何ですか。
いつどのように使用するかとその理由を説明する前に、 GO
が何であるか、および何でないかを正確に理解することが最初に重要です。
キーワードGO
は、SQL Server Management StudioとSQLCMDによって、1つのことだけを表すために使用されます。ステートメントのバッチの終わりです。実際、バッチを「GO」以外に終了するために使用するものを変更することもできます。
上記のスクリーンショットは、構成可能なSSMS内のオプションです。
しかし、バッチとは何ですか? このBOL参照 はそれを最もよく言います:
バッチは1つ以上のTransact-SQLステートメントのグループで、アプリケーションからSQL Serverに同時に送信されて実行されます。
そのような単純な。これは、アプリケーション(はい...アプリケーション)がSQL Serverにステートメントを送信するカスタム方法にすぎません。このアプリケーションのような例を見てみましょう。 PowerShellを使用して、SQL Serverにステートメントとバッチを送信するためのアプリケーションの動作を模倣します。
$ConnectionString = "data source = SomeSQLInstance; initial catalog = AdventureWorks2012; trusted_connection = true; application name = BatchTesting;"
try {
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.Connection = $SqlConnection
# first batch of statements
#
$SqlCmd.CommandText = "
select * from humanresources.department where departmentid = 1;
select * from humanresources.department where departmentid = 2;
select * from humanresources.department where departmentid = 3;
select * from humanresources.department where departmentid = 4;"
# execute the first batch
#
$SqlConnection.Open()
$SqlCmd.ExecuteNonQuery()
$SqlConnection.Close()
# second batch of statements
#
$SqlCmd.CommandText = "
select * from humanresources.department where departmentid = 5;
select * from humanresources.department where departmentid = 6;
select * from humanresources.department where departmentid = 7;
select * from humanresources.department where departmentid = 8;"
# execute the second batch
#
$SqlConnection.Open()
$SqlCmd.ExecuteNonQuery()
$SqlConnection.Close()
}
catch {
$SqlCmd.Dispose()
$SqlConnection.Dispose()
Write-Error $_.Exception
}
コメントはそれを提供しますが、プログラムで2つのbatchesをプログラムでSQL Serverに送信していることがわかります。それを確認しましょう。ここでの私の選択は、拡張イベントを使用することです。
create event session BatchTesting
on server
add event sqlserver.sql_batch_starting
(
set
collect_batch_text = 1
where
(
sqlserver.client_app_name = N'BatchTesting'
)
),
add event sqlserver.sql_batch_completed
(
set
collect_batch_text = 1
where
(
sqlserver.client_app_name = N'BatchTesting'
)
),
add event sqlserver.sql_statement_starting
(
set
collect_statement = 1
where
(
sqlserver.client_app_name = N'BatchTesting'
)
),
add event sqlserver.sql_statement_completed
(
set
collect_statement = 1
where
(
sqlserver.client_app_name = N'BatchTesting'
)
)
add target package0.event_file
(
set
filename = N'<MyXelLocation>\BatchTesting.xel'
);
go
alter event session BatchTesting
on server
state = start;
go
このXEventsセッションが実行しているのは、"BatchTesting"
という名前のアプリケーションから開始して完了するステートメントとバッチをキャプチャすることだけです(PowerShellコードの例で接続文字列に気付いた場合は、イベントの特定の発生元をすばやく確認できます) 「アプリケーション名」の接続文字列パラメータを使用し、それをフィルタリングすることにより)。
PowerShellコードを実行してこれらのバッチとステートメントを送信すると、次の結果が表示されます。
スクリーンショットからわかるように、ステートメントが2つの異なるバッチにどのように分割されているかは明らかです。これは、バッチの呼び出しに使用した方法からも明らかです。そして、batch_text
の最初の出現のsql_batch_starting
を調べると、そのバッチに含まれているすべてのステートメントを確認できます。
select * from humanresources.department where departmentid = 1;
select * from humanresources.department where departmentid = 2;
select * from humanresources.department where departmentid = 3;
select * from humanresources.department where departmentid = 4;
whatのバッチの説明により、whenバッチを終了します。バッチのルールは バッチに関するこのBOLリファレンス にあります。
CREATE DEFAULT、CREATE FUNCTION、CREATE PROCEDURE、CREATE RULE、CREATE SCHEMA、CREATE TRIGGER、およびCREATE VIEWステートメントは、バッチ内の他のステートメントと組み合わせることはできません。 CREATEステートメントはバッチを開始する必要があります。そのバッチで続く他のすべてのステートメントは、最初のCREATEステートメントの定義の一部として解釈されます。
テーブルを変更してから、同じバッチで参照される新しい列を変更することはできません。
EXECUTEステートメントがバッチの最初のステートメントである場合、EXECUTEキーワードは不要です。 EXECUTEステートメントがバッチ内の最初のステートメントでない場合は、EXECUTEキーワードが必要です。
同様に、バッチ中に発生する特定のランタイムエラー(コンパイルエラーではバッチの実行を開始できません)は、異なる動作を引き起こす可能性があります:バッチを完全に中止する、またはバッチを続行して問題のステートメントのみを中止する(上記)リンクは2つの本当に良い例を示します。たとえば、算術オーバーフローエラーはバッチの実行を停止しますが、制約違反エラーは現在のステートメントの完了を妨げるだけで、バッチは実行を続けます)。
しかし、私たちの専門職の多くのことと同様に、T-SQLコードの個人および作成者がバッチを終了する方法の背後には、個人的な好みが大きな原動力になります。一部の人は、絶対にバッチを明示的に定義するだけですする必要がある(これらの要件については上記を参照)、その他の人は、バッチをプログラムで終了しますSSMSのクエリウィンドウで単一のステートメントのみを実行している場合でも、100%の時間。ほとんどの人は通常、これら2つの境界の真ん中のどこかに落ちます。価値があるのは、ステートメントターミネーターのフォローが同じで、強制される要件がほとんどないことです。このすべての大部分はコードスタイルであり、強制されません(SSMSおよびSQLCMDで)。