Antworten:
GO ist wie das Ende eines Skripts.
Sie können mehrere CREATE TABLE-Anweisungen haben, die durch GO getrennt sind. Auf diese Weise können Sie einen Teil des Skripts von einem anderen isolieren, aber alles in einem Block einreichen.
BEGIN und END sind wie {und} in C / ++ / #, Java usw.
Sie banden einen logischen Codeblock. Ich neige dazu, BEGIN und END zu Beginn und am Ende einer gespeicherten Prozedur zu verwenden, aber dies ist dort nicht unbedingt erforderlich. Wo es notwendig ist, sind Schleifen und IF-Anweisungen usw., wo Sie mehr als einen Schritt benötigen ...
IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
INSERT INTO Log SELECT @id, 'deleted'
DELETE my_table WHERE id = @id
END
Sie benötigen BEGIN ... END, um einen Block zu erstellen, der mehr als eine Anweisung umfasst. Wenn Sie also zwei Dinge in einem 'Bein' einer IF-Anweisung ausführen möchten oder wenn Sie mehr als eine Aufgabe im Hauptteil einer WHILE-Schleife ausführen möchten, müssen Sie diese Anweisungen mit BEGIN in Klammern setzen ... ENDE.
Das GO-Schlüsselwort ist nicht Teil von SQL. Es wird nur von Query Analyzer verwendet, um Skripte in "Stapel" zu unterteilen, die unabhängig voneinander ausgeführt werden.
GO ist kein Schlüsselwort in SQL Server. Es ist ein Batch-Separator. GO beendet eine Reihe von Anweisungen. Dies ist besonders nützlich, wenn Sie etwas wie SQLCMD verwenden. Stellen Sie sich vor, Sie geben SQL-Anweisungen in der Befehlszeile ein. Sie möchten nicht unbedingt, dass das Objekt jedes Mal ausgeführt wird, wenn Sie eine Anweisung beenden. Daher unternimmt SQL Server nichts, bis Sie "GO" eingeben.
Ebenso müssen vor dem Start Ihres Stapels häufig einige Objekte sichtbar sein. Angenommen, Sie erstellen eine Datenbank und fragen sie dann ab. Du kannst nicht schreiben:
CREATE DATABASE foo;
USE foo;
CREATE TABLE bar;
weil foo für den Stapel, der die CREATE TABLE ausführt, nicht existiert. Sie müssten dies tun:
CREATE DATABASE foo;
GO
USE foo;
CREATE TABLE bar;
BEGIN und END wurden von anderen gut beantwortet.
Wie Gary betont, ist GO ein Batch-Trennzeichen, das von den meisten von Microsoft bereitgestellten Client-Tools wie isql, sqlcmd, query analyzer und SQL Server Management Studio verwendet wird. (Zumindest einige der Tools ermöglichen das Ändern des Batch-Separators. Ich habe noch nie eine Verwendung zum Ändern des Batch-Separators gesehen.)
Um die Frage zu beantworten, wann GO verwendet werden soll, muss bekannt sein, wann SQL in Stapel aufgeteilt werden muss.
Einige Anweisungen müssen die erste Anweisung eines Stapels sein.
select 1
create procedure #Zero as
return 0
Unter SQL Server 2000 lautet der Fehler:
Msg 111, Level 15, State 1, Line 3
'CREATE PROCEDURE' must be the first statement in a query batch.
Msg 178, Level 15, State 1, Line 4
A RETURN statement with a return value cannot be used in this context.
Unter SQL Server 2005 ist der Fehler weniger hilfreich:
Msg 178, Level 15, State 1, Procedure #Zero, Line 5
A RETURN statement with a return value cannot be used in this context.
Verwenden Sie GO
diese Option, um Anweisungen, die der Beginn eines Stapels sein müssen, von den Anweisungen zu trennen, die in einem Skript davor stehen.
Wenn ein Skript ausgeführt wird, führen viele Fehler dazu, dass die Ausführung des Stapels gestoppt wird. Der Client sendet jedoch einfach den nächsten Stapel. Die Ausführung des Skripts wird nicht gestoppt. Ich benutze dies oft beim Testen. Ich werde das Skript mit der Starttransaktion beginnen und mit dem Rollback enden, wobei alle Tests in der Mitte durchgeführt werden:
begin transaction
go
... test code here ...
go
rollback transaction
Auf diese Weise kehre ich immer in den Startzustand zurück, auch wenn im Testcode ein Fehler aufgetreten ist. Die Anweisungen zum Starten und Zurücksetzen von Transaktionen, die Teil eines separaten Stapels sind, treten weiterhin auf. Wenn sie sich nicht in separaten Stapeln befinden, verhindert ein Syntaxfehler, dass die Transaktion beginnt, da ein Stapel als Einheit analysiert wird. Und ein Laufzeitfehler würde das Rollback verhindern.
Wenn Sie ein Installationsskript ausführen und mehrere Stapel in einer Datei haben, verhindert ein Fehler in einem Stapel nicht, dass das Skript weiter ausgeführt wird, was zu einem Durcheinander führen kann. (Vor der Installation immer sichern.)
In Bezug auf das, was Dave Markel hervorgehoben hat, gibt es Fälle, in denen die Analyse fehlschlägt, weil SQL Server im Datenwörterbuch nach Objekten sucht, die früher im Stapel erstellt wurden. Die Analyse kann jedoch erfolgen, bevor Anweisungen ausgeführt werden. Manchmal ist dies ein Problem, manchmal nicht. Ich kann kein gutes Beispiel finden. Wenn Sie jedoch jemals den Fehler "X existiert nicht" erhalten, wird dieser durch diese Anweisung eindeutig in Stapel aufgeteilt.
Und noch eine letzte Anmerkung. Die Transaktion kann mehrere Stapel umfassen. (Siehe oben.) Variablen erstrecken sich nicht über Stapel.
declare @i int
set @i = 0
go
print @i
Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@i".
GO beendet einen Stapel, Sie müssten ihn nur sehr selten im Code verwenden. Beachten Sie, dass bei Verwendung in einem gespeicherten Prozess kein Code nach dem GO ausgeführt wird, wenn Sie den Prozess ausführen.
BEGIN und END werden für alle prozeduralen Typanweisungen mit mehreren zu verarbeitenden Codezeilen benötigt. Sie benötigen sie für WHILE-Schleifen und Cursor (die Sie natürlich möglichst vermeiden) und IF-Anweisungen (technisch gesehen benötigen Sie sie nicht für eine IF-Anweisung, die nur eine Codezeile enthält, dies ist jedoch einfacher Behalten Sie den Code bei, wenn Sie ihn immer nach einer IF eingeben. CASE-Anweisungen verwenden ebenfalls ein END, haben jedoch kein BEGIN.
Nachdem ich heute mit diesem Problem gerungen habe, ist meine Meinung folgende: BEGIN ... END Klammern Code genau wie {....} in C-Sprachen, z. B. Codeblöcke für if ... else und Schleifen
GO wird (muss verwendet werden), wenn nachfolgende Anweisungen auf einem Objekt beruhen, das durch eine vorherige Anweisung definiert wurde. Die USE-Datenbank ist oben ein gutes Beispiel, aber das Folgende wird Sie auch beißen:
alter table foo add bar varchar(8);
-- if you don't put GO here then the following line will error as it doesn't know what bar is.
update foo set bar = 'bacon';
-- need a GO here to tell the interpreter to execute this statement, otherwise the Parser will lump it together with all successive statements.
Mir scheint, das Problem ist folgendes: Der SQL Server SQL Parser kann im Gegensatz zum Oracle nicht erkennen, dass Sie ein neues Symbol in der ersten Zeile definieren und dass es in Ordnung ist, in den folgenden Zeilen darauf zu verweisen. Es "sieht" das Symbol erst, wenn es auf ein GO-Token stößt, das es anweist, das vorhergehende SQL seit dem letzten GO auszuführen. An diesem Punkt wird das Symbol auf die Datenbank angewendet und für den Parser sichtbar.
Warum es das Semikolon nicht einfach als semantische Unterbrechung behandelt und Aussagen einzeln anwendet, weiß ich nicht und wünsche es mir. Der einzige Bonus, den ich sehen kann, ist, dass Sie eine print () - Anweisung direkt vor dem GO platzieren können. Wenn eine der Anweisungen fehlschlägt, wird der Druck nicht ausgeführt. Viel Ärger für einen kleinen Gewinn.