Was ist eine „Charge“ und warum wird GO verwendet?


134

Ich habe MSDN usw. gelesen und gelesen. Ok, es signalisiert das Ende eines Stapels.

Was macht eine Charge aus? Ich verstehe nicht, warum ich gehen muss, wenn ich eine Reihe von Skripten einfüge, die alle gleichzeitig ausgeführt werden sollen.

Ich habe GO nie verstanden. Kann jemand dies besser erklären und wann ich es verwenden muss (nach wie vielen oder welcher Art von Transaktionen)?

Zum Beispiel, warum sollte ich nach jedem Update hier GO brauchen:

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

 GO

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


FWIW, es scheint, als ob a goauch declare @fooVariablendeklarationen zurücksetzt / löscht - ich habe festgestellt , dass Sie @ foo- Fehler deklarieren müssen , bis ich das auskommentiert habego .
JL Peyret

Antworten:


107

GOist nicht richtig ein TSQL-Befehl.

Stattdessen ist es ein Befehl an das spezifische Client-Programm der eine Verbindung zu einem SQL-Server (Sybase oder Microsoft - nicht sicher, was Oracle tut) herstellt und dem Client-Programm signalisiert, dass der bis zum Start eingegeben wurde, erforderlich ist an den Server gesendet werden, um ausgeführt zu werden.

Warum / wann brauchst du es?

  • GO in MS SQL Server verfügt über einen Parameter "count", sodass Sie ihn als Verknüpfung "N-mal wiederholen" verwenden können.

  • Extrem große Updates füllen möglicherweise das Protokoll des SQL Servers. Um dies zu vermeiden, müssen sie möglicherweise über in kleinere Chargen aufgeteilt werden go.

    Wenn in Ihrem Beispiel die Aktualisierung für eine Reihe von Ländercodes ein solches Volumen aufweist, dass der Protokollspeicherplatz knapp wird, besteht die Lösung darin, jeden Ländercode in eine separate Transaktion zu unterteilen. Dies kann durch Trennen auf dem Client mit erfolgen go.

  • Einige SQL-Anweisungen MÜSSEN durch GO von den folgenden getrennt werden, damit sie funktionieren.

    Beispielsweise können Sie eine Tabelle nicht löschen und dieselbe gleichnamige Tabelle in einer einzigen Transaktion neu erstellen, zumindest nicht in Sybase (ebenso zum Erstellen von Prozeduren / Triggern):

> 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
Die GO-Anweisung erstellt keine Transaktion. Wenn Sie mehrere GO-Anweisungen in eine BEGIN TRANSACTION-Anweisung aufnehmen und am Ende ein ROLLBACK ausführen, werden alle GOs zurückgesetzt. Und wenn Sie in einem GO in der Mitte einen Fehler erhalten und am Ende COMMIT ausführen, werden alle GO ohne Fehler festgeschrieben. Ist irgendwie knifflig.
TZ

7
GOerstellt keine "Transaktion für Sie". Wenn Sie nicht in einer expliziten Transaktion ausgeführt werden, erstellt jede Anweisung ohnehin eine eigene Transaktion. Es ist vollständig orthogonal. Wenn Sie ein größeres Update in kleinere Schritte aufteilen möchten, können Sie dies weiterhin in einem einzigen Stapel wie im allgemeinen WHILE @@ROWCOUNT > 0Muster tun .
Martin Smith

3
Wenn Sie nicht in einer expliziten Transaktion ausgeführt UPDATE T1 SET X =2;UPDATE T1 SET X =2;werden, werden diese ohnehin als zwei separate Transaktionen ausgeführt . Das Hinzufügen von GOmacht absolut keinen Unterschied. Und in ähnlicher Weise , wenn Sie sind in einer expliziten Transaktion läuft es Chargen umspannt und wieder GO macht keinen Unterschied.
Martin Smith

4
Genauso wie die Klarstellung für jeden, der dies später liest, GOabsolut nichts mit Transaktionen zu tun hat und die Antworten zum zweiten Punkt über Transaktionen und die Größe einer Protokolldatei falsch macht. GOwird überhaupt keine Wirkung haben. Die erste und dritte Antwort sind richtig. Darüber hinaus gibt es Zeiten, in denen Sie Anweisungen in separate Stapel aufteilen müssen. Beispielsweise können Sie einer Tabelle keine Spalte hinzufügen und diese Spalte später im selben Stapel verwenden. (Fortsetzung)
Robert McKee

4
Da einige Fehler einen Stapel abbrechen (einige Fehler brechen nur eine Anweisung ab), spielt dies außerdem eine Rolle bei der Fehlererkennung und -behebung. Und bestimmte Anweisungen ( CREATE VIEWusw.) müssen in einem eigenen Stapel vorliegen.
Robert McKee

26

GO ist keine Aussage, es ist ein Batch-Trennzeichen.

Die durch getrennten Blöcke GOwerden vom Client zur Verarbeitung an den Server gesendet, und der Client wartet auf ihre Ergebnisse.

Zum Beispiel, wenn Sie schreiben

DELETE FROM a
DELETE FROM b
DELETE FROM c

wird dies als 3einzeilige Abfrage an den Server gesendet .

Wenn du schreibst

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

wird dies als 3einzeilige Abfrage an den Server gesendet .

GOselbst geht nicht zum Server (kein Wortspiel beabsichtigt). Es ist ein reines clientseitig reserviertes Wort und wird nur von erkanntSSMS undosql .

Wenn Sie ein benutzerdefiniertes Abfragetool verwenden, um es über die Verbindung zu senden, erkennt der Server es nicht einmal und gibt einen Fehler aus.


4
Warum müssen Sie überhaupt stapeln?
PositiveGuy

3
GO bedeutet also, es zu senden und den nächsten Stapel erst auszuführen, wenn der Client "OK, dieser Stapel ist fertig und erfolgreich" erhält. Dies ist im Grunde das, was der GO tut, damit der nächste Stapel erfolgreich ausgeführt werden kann und der Client weiß, wofür Stellen Sie sicher, dass der Stapel serverseitig ausgeführt wird.
PositiveGuy

3
@coffeeaddict: im Grunde ja. Darüber hinaus müssen einige Anweisungen in ihren Stapeln an erster Stelle stehen (wie CREATE SCHEMA). andere erfordern, die einzigen Aussagen in ihren Chargen zu sein (wie SET SHOWPLAN_XML ON)
Quassnoi

19

Viele Befehle müssen in einem eigenen Stapel sein, wie z CREATE PROCEDURE

Wenn Sie einer Tabelle eine Spalte hinzufügen, sollte sie sich in einem eigenen Stapel befinden. Wenn Sie versuchen, die neue Spalte im selben Stapel auszuwählen, schlägt dies fehl, da die Spalte zum Zeitpunkt der Analyse / Kompilierung nicht vorhanden ist.

GO wird von den SQL-Tools verwendet, um dies aus einem Skript herauszuarbeiten: Es ist kein SQL-Schlüsselwort und wird von der Engine nicht erkannt.

Dies sind zwei konkrete Beispiele für die tägliche Verwendung von Chargen.

Bearbeiten: In Ihrem Beispiel brauchen Sie nicht GO ...

Bearbeiten Sie 2, Beispiel. Sie können nicht in einem Stapel löschen, erstellen und berechtigen ... nicht zuletzt, wo ist das Ende der gespeicherten Prozedur?

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

Manchmal muss immer wieder derselbe Befehl oder Befehlssatz ausgeführt werden. Dies kann sein, um Testdaten einzufügen oder zu aktualisieren, oder um Ihren Server für Leistungstests zu belasten. Was auch immer benötigt wird, der einfachste Weg, dies zu tun, besteht darin, eine while-Schleife einzurichten und Ihren Code auszuführen. In SQL 2005 gibt es jedoch einen noch einfacheren Weg, dies zu tun.

Angenommen, Sie möchten eine Testtabelle erstellen und mit 1000 Datensätzen laden. Sie könnten den folgenden Befehl ausgeben, der 1000 Mal denselben Befehl ausführt:

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

Quelle: http://www.mssqltips.com/tip.asp?tip=1216

Ansonsten markiert es das "Ende" eines SQL-Blocks (z. B. in einer gespeicherten Prozedur) ... Das heißt, Sie befinden sich wieder in einem "sauberen" Zustand ... eG: In der Anweisung verwendete Parameter, bevor der Code zurückgesetzt wird ( nicht mehr definiert)


Ok, warum brauchst du GO? Damit Sie wissen, dass die Tabelle erstellt wurde, bevor die insert-Anweisung ausgeführt wird? Ich verstehe es immer noch nicht.
PositiveGuy

Wenn ich in Ihrem Beispiel keine GOs habe, wird die Tabelle zuerst erstellt und ist jetzt dort, sodass die Einfügung funktionieren sollte. Ich verstehe nicht, wofür der GO ist, wenn ich die Tabelle erstellt habe ... sie ist für die nächste Einfügung verfügbar, nicht wahr?!?!?!
PositiveGuy

2
@coffeeaddict: nein. Der "Batch" wird auf einmal analysiert und kompiliert. Zur Kompilierungszeit ist dbo.TEST nicht vorhanden. Sie instanziieren kein Objekt und SQL ist kein zeilenweiser Prozedurcode
gbn

3

Wie bereits gesagt, ist "GO" nicht Teil von T-SQL. "GO" ist ein Batch-Separator in SSMS , einer Client-Anwendung, mit der Abfragen an die Datenbank werden. Dies bedeutet, dass deklarierte Variablen und Tabellenvariablen nicht vom Code vor dem "GO" zum darauf folgenden Code bestehen bleiben.

Tatsächlich ist GO einfach das Standardwort, das von SSMS verwendet wird. Dies kann in den Optionen geändert werden, wenn Sie möchten. Ändern Sie für ein bisschen Spaß die Option auf dem System einer anderen Person, um "SELECT" als Batch-Separator anstelle von "GO" zu verwenden. Vergib mir mein grausames Kichern.


1
Hier ist tatsächlich ein schwerwiegender Punkt zu beachten: Sie sollten GO so behandeln, als wäre es ein Schlüsselwort, obwohl dies nicht der Fall ist. Sie sollten es auch nie ändern. Fehler, die durch die Wiederverwendung spezieller Bezeichner verursacht werden, können sehr schwer zu debuggen sein.
Jørgen Fogh

@ The Dixie Flatline: Sind Sie sicher, dass die deklarierten Variablen nicht bestehen bleiben? In MSSQL 2016 erhalte ich beim Ausführen den Fehler "Variable bereits deklariert": deklariere $ test int; setze $ test = 5; wähle $ test go; deklariere $ test int; - Ersetzen Sie $ durch <at>, können in SE-Kommentaren nicht mehrere <at> verwenden.
Wouter

0

Es wird verwendet, um logische Blöcke zu teilen. Ihr Code wird in die SQL-Befehlszeile interpretiert und dies zeigt den nächsten Codeblock an.

Es kann jedoch als rekursive Anweisung mit einer bestimmten Nummer verwendet werden.

Versuchen:

exec sp_who2  
go 2

Einige Aussagen müssen von GO abgegrenzt werden:

use DB
create view thisViewCreationWillFail
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.