Kiedy muszę używać Begin / End Blocks i słowa kluczowego Go w programie SQL Server?

103

Czy ktoś może mi powiedzieć, kiedy i gdzie muszę używać begini endblokować w SQL Server?
Co dokładnie robi Gosłowo kluczowe?

Tarik
źródło

Odpowiedzi:

116

GO jest jak koniec skryptu.

Możesz mieć wiele instrukcji CREATE TABLE oddzielonych znakiem GO. Jest to sposób na odizolowanie jednej części skryptu od drugiej, ale przesłanie go w całości w jednym bloku.


BEGIN i END są takie same jak {i} w C / ++ / #, Javie itd.

Powiązali logiczny blok kodu. Zwykle używam BEGIN i END na początku i na końcu procedury składowanej, ale nie jest to bezwzględnie konieczne. Tam, gdzie jest to konieczne, są pętle, instrukcje IF itp., Gdzie potrzebujesz więcej niż jednego kroku ...

IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
   INSERT INTO Log SELECT @id, 'deleted'
   DELETE my_table WHERE id = @id
END
MatBailie
źródło
Czy próbowałeś utworzyć SP bez BEGIN i END? IIRC, tylko pierwsza linia jest uwzględniona w SP, reszta jest po prostu tam wykonywana, a następnie ...
cjk.
2
Z pewnością nie jest to moje doświadczenie od SQL Server 2000.
MatBailie,
1
Czy BEGIN i END definiują również nowy zakres?
samis
2
Tak. Wszystko, co zadeklarowano na zewnątrz, jest widoczne w środku, ale wszystko, co zadeklarowano wewnątrz, wyjdzie poza zakres na końcu.
MatBailie
36

Potrzebujesz BEGIN ... END, aby utworzyć blok obejmujący więcej niż jedną instrukcję. Tak więc, jeśli chciałbyś zrobić 2 rzeczy w jednej `` nodze '' instrukcji IF lub jeśli chciałbyś zrobić więcej niż jedną rzecz w treści pętli WHILE, musisz umieścić te instrukcje w nawiasach BEGIN ... KONIEC.

Słowo kluczowe GO nie jest częścią języka SQL. Jest używany tylko przez Query Analyzer do dzielenia skryptów na „partie”, które są wykonywane niezależnie.

Gary McGill
źródło
28

GO nie jest słowem kluczowym w SQL Server; jest to separator partii. GO kończy zestaw instrukcji. Jest to szczególnie przydatne, gdy używasz czegoś takiego jak SQLCMD. Wyobraź sobie, że wpisujesz instrukcje SQL w wierszu poleceń. Niekoniecznie chcesz, aby ta rzecz była wykonywana za każdym razem, gdy kończysz instrukcję, więc SQL Server nic nie robi, dopóki nie wpiszesz „GO”.

Podobnie, zanim rozpocznie się tworzenie partii, często trzeba mieć widoczne obiekty. Na przykład, powiedzmy, że tworzysz bazę danych, a następnie wykonujesz do niej zapytanie. Nie możesz pisać:

CREATE DATABASE foo;
USE foo;
CREATE TABLE bar;

ponieważ foo nie istnieje dla wsadu, który wykonuje CREATE TABLE. Musisz to zrobić:

CREATE DATABASE foo;
GO
USE foo;
CREATE TABLE bar;
Dave Markle
źródło
13

Inni dobrze odpowiedzieli na BEGIN i END.

Jak zauważa Gary, GO to separator wsadowy, używany przez większość narzędzi klienckich dostarczonych przez Microsoft, takich jak isql, sqlcmd, analizator zapytań i SQL Server Management Studio. (Przynajmniej niektóre narzędzia pozwalają na zmianę separatora partii. Nigdy nie widziałem zastosowania do zmiany separatora partii).

Aby odpowiedzieć na pytanie, kiedy używać GO, trzeba wiedzieć, kiedy SQL należy podzielić na partie.

Niektóre instrukcje muszą być pierwszymi instrukcjami z serii.

select 1
create procedure #Zero as
    return 0

W programie SQL Server 2000 błąd to:

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.

W SQL Server 2005 błąd jest mniej pomocny:

Msg 178, Level 15, State 1, Procedure #Zero, Line 5
A RETURN statement with a return value cannot be used in this context.

Dlatego użyj, GOaby oddzielić instrukcje, które muszą być początkiem partii, od instrukcji, które ją poprzedzają w skrypcie.

Podczas uruchamiania skryptu wiele błędów spowoduje zatrzymanie wykonywania partii, ale wtedy klient po prostu wyśle ​​kolejną partię, wykonanie skryptu nie zostanie zatrzymane. Często używam tego w testach. Zacznę skrypt od początku transakcji i zakończę wycofaniem, wykonując wszystkie testy w środku:

begin transaction
go
... test code here ...
go
rollback transaction

W ten sposób zawsze wracam do stanu początkowego, nawet jeśli wystąpił błąd w kodzie testowym, nadal zdarzają się instrukcje rozpoczęcia i wycofywania transakcji będące częścią oddzielnych partii. Gdyby nie były w oddzielnych partiach, błąd składni uniemożliwiłby rozpoczęcie transakcji, ponieważ partia jest analizowana jako jednostka. A błąd w czasie wykonywania uniemożliwiłby wycofanie.

Ponadto, jeśli wykonujesz skrypt instalacyjny i masz kilka partii w jednym pliku, błąd w jednej partii nie uniemożliwi kontynuacji działania skryptu, co może spowodować bałagan. (Zawsze wykonaj kopię zapasową przed instalacją).

W związku z tym, na co zwrócił uwagę Dave Markel, istnieją przypadki, w których analiza nie powiedzie się, ponieważ SQL Server szuka w słowniku danych obiektów, które zostały utworzone wcześniej w partii, ale analiza może nastąpić przed uruchomieniem jakichkolwiek instrukcji. Czasami jest to problem, czasami nie. Nie potrafię podać dobrego przykładu. Ale jeśli kiedykolwiek pojawi się błąd „X nie istnieje”, kiedy to po prostu będzie istnieć przez to stwierdzenie, podziel na partie.

I ostatnia uwaga. Transakcja może obejmować partie. (Zobacz powyżej). Zmienne nie obejmują partii.

declare @i int
set @i = 0
go
print @i

Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@i".
Shannon Severance
źródło
1
Właśnie tego potrzebowałem, dzięki: „Transakcja może obejmować partie. Zmienne nie obejmują partii”.
Gary
3

GO kończy partię, bardzo rzadko trzeba by było użyć go w kodzie. Należy pamiętać, że jeśli użyjesz go w przechowywanym procencie, żaden kod po GO nie zostanie wykonany podczas wykonywania proc.

BEGIN i END są potrzebne w przypadku wszystkich instrukcji typu proceduralnego z wieloma wierszami kodu do przetworzenia. Będziesz ich potrzebował do pętli i kursorów WHILE (których oczywiście unikniesz, jeśli w ogóle to możliwe) i instrukcji IF (no cóż, technicznie rzecz biorąc, nie potrzebujesz ich do instrukcji IF, która ma tylko jedną linię kodu, ale łatwiej jest zachowaj kod, jeśli zawsze umieszczasz je po IF). Instrukcje CASE również używają END, ale nie mają BEGIN.

HLGEM
źródło
Czy jakikolwiek kod po GO rzeczywiście zostałby zapisany w przechowywanym procencie? czy instrukcja CREATE lub ALTER nie byłaby przetwarzana tak, jakby kod po komendzie GO nie istniał? A WTEDY kod po GO zostanie wykonany tak, jakby był to własny skrypt?
MatBailie
Co mają z tym wspólnego kursory?
Gary McGill
3

Po dzisiejszym zmaganiu się z tym problemem moja opinia jest taka: BEGIN ... END w nawiasach klamrowych, tak jak {....} w językach C, np. Bloki kodu dla if ... else i pętli

GO jest (musi być) używane, gdy kolejne instrukcje opierają się na obiekcie zdefiniowanym przez poprzednią instrukcję. Baza danych USE jest dobrym przykładem powyżej, ale poniższe również mogą Cię ugryźć:

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.

Wydaje mi się, że problem jest następujący: SQL Server SQL Parser, w przeciwieństwie do Oracle, nie jest w stanie zdać sobie sprawy, że definiujesz nowy symbol w pierwszym wierszu i że można odwoływać się do kolejnych wierszy. Nie „widzi” symbolu, dopóki nie napotka tokenu GO, który nakazuje mu wykonanie poprzedniego kodu SQL od ostatniego GO, w którym to momencie symbol jest stosowany do bazy danych i staje się widoczny dla parsera.

Dlaczego nie traktuje średnika po prostu jako przerwy semantycznej i nie stosuje instrukcji indywidualnie, nie wiem i chciałbym, żeby tak było. Jedynym bonusem, jaki widzę, jest to, że możesz umieścić instrukcję print () tuż przed GO i jeśli któraś z instrukcji zawiedzie, print nie zostanie wykonany. Dużo kłopotów za niewielki zysk.

matao
źródło