「バッチ」とは何ですか。GOが使用されるのはなぜですか。


134

私は、MSDNなどを読んだり読んだりしました。それで、バッチの終わりを示しています。

バッチを定義するものは何ですか?多数のスクリプトを同時に貼り付けて実行するときに、なぜ移動する必要があるのか​​わかりません。

私はGOを理解したことがありません。誰もがこれをよりよく説明できますか、それを使用する必要があるとき(トランザクションの数またはタイプの後に)?

たとえば、ここで更新するたびにGOが必要になるのはなぜですか。

 UPDATE [Country]
   SET [CountryCode] = 'IL'
 WHERE code = 'IL'

 GO

 UPDATE [Country]
   SET [CountryCode] = 'PT'
 WHERE code = 'PT'


FWIW、まるで変数宣言goもリセット/クリアするようdeclare @fooです-私がコメントアウトするまで、@ fooエラーを宣言する必要がありますgo
JL Peyret

回答:


107

GO正しくTSQLコマンドではありません

代わりに、SQLサーバーに接続する特定のクライアントプログラムへのコマンド(SybaseまたはMicrosoft-Oracleの動作は不明)であり、「go」が必要になるまで入力されたコマンドのセットをクライアントプログラムに通知します。サーバーに送信されて実行されます。

なぜ/いつ必要ですか?

  • MS SQLサーバーのGOには「count」パラメーターがあるため、「N回繰り返す」ショートカットとして使用できます。

  • 極端に大きな更新を行うと、SQLサーバーのログがいっぱいになる可能性があります。これを回避するには、を使用してそれらを小さなバッチに分離する必要がある場合がありgoます。

    あなたの例では、国コードのセットの更新でログスペースが不足するほどのボリュームがある場合、解決策は、国コードを個別のトランザクションに分離することgoです。

  • 一部のSQLステートメントは、機能するために、次のステートメントからGOで分離する必要があります。

    たとえば、少なくともSybaseでは、テーブルを削除して同じ名前のテーブルを単一のトランザクションで再作成することはできません(プロシージャ/トリガーの作成については同じです)。

> drop table tempdb.guest.x1          
> create table tempdb.guest.x1 (a int)
> go
  Msg 2714, Level 16, State 1
  Server 'SYBDEV', Line 2
  There is already an object named 'x1' in the database.   
  
> drop table tempdb.guest.x1          
> go
> create table tempdb.guest.x1 (a int)
> go
>

4
GOステートメントはトランザクションを作成しません。1つのBEGIN TRANSACTIONステートメントに複数のGOステートメントを含め、最後にROLLBACKを実行すると、すべてのGOがロールバックされます。途中で1つのGOでエラーが発生し、最後にCOMMITを実行すると、エラーのないすべてのGOがコミットされます。ちょっとトリッキーです。
TZ

7
GO「あなたのためのトランザクションを作成する」わけではありません。明示的なトランザクションで実行していない場合、各ステートメントはとにかく独自のトランザクションを作成します。それは完全に直交しています。大きな更新を小さなステップに分割したい場合でも、一般的なWHILE @@ROWCOUNT > 0パターンのように単一のバッチで行うことができます。
マーティン・スミス

3
明示的なトランザクションで実行していない場合は、とにかくUPDATE T1 SET X =2;UPDATE T1 SET X =2; 2つの別個のトランザクションとして実行されます。を追加してもGO、まったく違いはありません。そして、あなたが同様に場合されている、それは再びバッチをまたがり、明示的なトランザクションで実行すると、GO 違いはありません。
マーティン・スミス

4
後でこれを読んでいる人のための説明と同じように... GOトランザクションとはまったく関係がなく、トランザクションとログファイルのサイズに関する答えが2番目のポイントになります。 GO何の効果もありません。最初と3番目の答えは正しいです。さらに、ステートメントを別々のバッチに分割する必要がある場合があります。たとえば、列をテーブルに追加して、その列を後で同じバッチで使用することはできません。(続き)
Robert McKee

4
さらに、一部のエラーはバッチを中止する(一部のエラーはステートメントのみを中止する)ため、エラーの検出と回復にも役立ちます。また、特定のステートメント(CREATE VIEWなど)を独自のバッチに含める必要があります。
ロバートマッキー

26

GO はステートメントではなく、バッチ区切り文字です。

で区切られたブロックGOは、クライアントによってサーバーに送信されて処理され、クライアントはその結果を待ちます。

たとえば、あなたが書く場合

DELETE FROM a
DELETE FROM b
DELETE FROM c

、これは単3一行のクエリとしてサーバーに送信されます。

あなたが書くなら

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

、これは31行のクエリとしてサーバーに送信されます。

GOそれ自体はサーバーに行きません(しゃれは意図されていません)。それは純粋なクライアント側の予約語だとのみによって認識されるSSMSosql

カスタムクエリツールを使用して接続経由で送信する場合、サーバーはそれを認識せず、エラーを発行します。


4
なぜバッチ処理をしなければならないのですか?
PositiveGuy

3
したがって、GOはそれを送信し、クライアントが「OK、そのバッチは完了し、成功しました」を受信するまで次のバッチを実行しないことを基本的にはGOが実行するため、次のバッチを正常に実行でき、クライアントはサーバー側で完了する前に、バッチを確認してください。
PositiveGuy

3
@coffeeaddict:基本的にはい。さらに、いくつかのステートメントは、バッチの最初にする必要があります(などCREATE SCHEMA)。その他は、バッチ内の唯一のステートメントである必要があります(などSET SHOWPLAN_XML ON
Quassnoi 2010

19

多くのコマンドは、次のように独自のバッチにする必要があります CREATE PROCEDURE

または、テーブルに列を追加する場合は、独自のバッチに含める必要があります。同じバッチで新しい列をSELECTしようとすると、解析/コンパイル時に列が存在しないため、失敗します。

GOは、SQLツールでこれを1つのスクリプトから実行するために使用されます。これはSQLキーワードではなく、エンジンで認識されません。

これらは、バッチの日常的な使用の2つの具体的な例です。

編集:あなたの例では、GOは必要ありません...

編集2、例。ドロップ、作成、およびアクセス許可を1つのバッチで行うことはできません...特に、ストアドプロシージャの終わりはどこにありますか?

IF OBJECT_ID ('dbo.uspDoStuff') IS NOT NULL
    DROP PROCEDURE dbo.uspDoStuff
GO
CREATE PROCEDURE dbo.uspDoStuff
AS
SELECT Something From ATable
GO
GRANT EXECUTE ON dbo.uspDoStuff TO RoleSomeOne
GO

4

同じコマンドまたはコマンドのセットを何度も繰り返し実行する必要がある場合があります。これは、テストデータを挿入または更新する場合と、パフォーマンステストのためにサーバーに負荷をかける場合があります。これを行う最も簡単な方法は、whileループを設定してコードを実行することですが、SQL 2005ではさらに簡単な方法があります。

テストテーブルを作成して、1000レコードをロードするとします。次のコマンドを発行すると、同じコマンドが1000回実行されます。

CREATE TABLE dbo.TEST (ID INT IDENTITY (1,1), ROWID uniqueidentifier)
GO
INSERT INTO dbo.TEST (ROWID) VALUES (NEWID()) 
GO 1000

ソース:http : //www.mssqltips.com/tip.asp?tip=1216

それ以外は、SQLブロックの「終了」を示します(たとえば、ストアドプロシージャ)...再び「クリーン」な状態にあることを意味します... eG:コードがリセットされる前にステートメントで使用されたパラメーター(もう定義されていません)


では、GOが必要なのはなぜですか。挿入ステートメントが実行される前にテーブルが作成されたことを知っていますか?まだわかりません。
PositiveGuy

これについて私が考える方法を参照してください。例にGOがない場合、テーブルが最初に作成され、それが今そこにあるので、挿入は機能するはずです。テーブルを作成した場合、GOの目的がわかりません...次の挿入で使用できますか?!?!?!
PositiveGuy

2
@coffeeaddict:いいえ。「バッチ」は一度に解析およびコンパイルされます。コンパイル時には、dbo.TESTは存在しません。あなたはオブジェクトをインスタンス化しておらず、SQL
は行ごとの

3

すでに述べたように、「GO」はT-SQLの一部ではありません。「GO」は、データベースにクエリを送信するために使用されるクライアントアプリケーションであるSSMSのバッチ区切り文字です。つまり、宣言された変数とテーブル変数は、 "GO"の前のコードから、それに続くコードに永続化されません。

実際、GOは単にSSMSで使用されるデフォルトの単語です。これは、必要に応じてオプションで変更できます。少し面白くするために、他の誰かのシステムのオプションを変更して、「GO」の代わりに「SELECT」をバッチセパレータとして使用します。私の残酷な笑いを許してください。


1
ここで実際に重要なポイントがあります。GOはキーワードではないのに、キーワードであるかのように扱う必要があります。また、絶対に変更しないでください。特殊な識別子の再利用によって引き起こされるバグは、デバッグが非常に困難な場合があります。
ヨルゲンFogh

@The Dixie Flatline:宣言された変数が持続しないことを確信していますか?MSSQL 2016では、実行時に「変数はすでに宣言されています」というエラーが発生します。declare$ test int; $ test = 5に設定します。$ test goを選択します。$ test intを宣言します。-$を<at>で置き換えます。SEコメントで複数の<at>を使用することはできません。
Wouter

0

論理ブロックを分割するために使用されます。コードはsqlコマンドラインに解釈され、次のコードブロックを示します。

しかし、それは特定の番号を持つ再帰ステートメントとして使用できます。

試してください:

exec sp_who2  
go 2

一部のステートメントはGOで区切る必要があります。

use DB
create view thisViewCreationWillFail
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.