Co to jest „partia” i dlaczego używa się GO?


134

Przeczytałem i przeczytałem przez MSDN itp. Ok, więc sygnalizuje koniec partii.

Co definiuje partię? Nie rozumiem, dlaczego muszę iść, kiedy wklejam kilka skryptów, które mają być uruchomione w tym samym czasie.

Nigdy nie rozumiałem GO. Czy ktoś może to lepiej wytłumaczyć i kiedy muszę z tego skorzystać (po ilu lub jakiego rodzaju transakcjach)?

Na przykład, dlaczego miałbym potrzebować GO po każdej aktualizacji tutaj:

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

 GO

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


FWIW, wygląda na to, że a gotakże resetuje / czyści declare @foodeklaracje zmiennych - otrzymywałem, że musisz zadeklarować błędy @foo , dopóki nie skomentowałem go.
JL Peyret

Odpowiedzi:


107

GOnie jest poprawnie poleceniem TSQL.

Zamiast tego jest to polecenie do konkretnego programu klienckiego, który łączy się z serwerem SQL (Sybase lub Microsoft - nie wiem, co robi Oracle), sygnalizując programowi klienckiemu, że zestaw poleceń wprowadzonych do niego do momentu „rozpoczęcia” będzie wymagał do wysłania na serwer w celu wykonania.

Dlaczego / kiedy tego potrzebujesz?

  • GO w serwerze MS SQL ma parametr „count” - możesz więc używać go jako skrótu „powtórz N razy”.

  • Niezwykle duże aktualizacje mogą zapełnić dziennik serwera SQL. Aby tego uniknąć, może być konieczne rozdzielenie ich na mniejsze partie za pomocą go.

    W twoim przykładzie, jeśli aktualizacja zestawu kodów krajów ma taką objętość, że zabraknie miejsca w dzienniku, rozwiązaniem jest rozdzielenie każdego kodu kraju na osobną transakcję - co można zrobić, oddzielając je na kliencie za pomocą go.

  • Niektóre instrukcje SQL MUSZĄ być oddzielone znakiem GO od następujących, aby działały.

    Na przykład nie można usunąć tabeli i ponownie utworzyć tabeli o tej samej nazwie w jednej transakcji, przynajmniej w Sybase (tak samo jak w przypadku tworzenia procedur / wyzwalaczy):

> 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
Instrukcja GO nie tworzy transakcji. Jeśli dołączysz wiele instrukcji GO do jednej instrukcji BEGIN TRANSACTION, a na końcu wykonasz ROLLBACK, wszystkie instrukcje GO zostaną wycofane. A jeśli w jednym GO pośrodku dostaniesz jakiś błąd, a na końcu zrobisz COMMIT, wszystko GO bez błędu zostanie zatwierdzone. To trochę trudne.
TZ

7
GOnie „tworzy transakcji za Ciebie”. Jeśli nie prowadzisz jawnej transakcji, każda instrukcja i tak utworzy własną transakcję. Jest całkowicie ortogonalny. Jeśli chcesz podzielić większą aktualizację na mniejsze kroki, nadal możesz to zrobić w jednej partii, tak jak w przypadku zwykłego WHILE @@ROWCOUNT > 0wzorca.
Martin Smith

3
Jeśli nie są uruchomione w jawnej transakcji wtedy UPDATE T1 SET X =2;UPDATE T1 SET X =2;będzie działać jako dwóch odrębnych transakcji w każdym razie . Dodanie nie GOrobi żadnej różnicy. I podobnie, jeśli uruchomione w jawnej transakcji to rozciąga partii i znowu GO nie robi różnicy.
Martin Smith

4
Tak jak wyjaśnienie dla każdego, kto to przeczyta później ... GOnie ma absolutnie nic wspólnego z transakcjami i sprawia, że ​​odpowiedzi na drugi punkt dotyczący transakcji i rozmiaru pliku dziennika są nieprawidłowe. GOnie przyniesie żadnego efektu. Pierwsza i trzecia odpowiedź są poprawne. Ponadto czasami trzeba rozdzielić instrukcje na osobne partie, na przykład nie można dodać kolumny do tabeli, a następnie użyć tej kolumny później w tej samej partii. (ciąg dalszy)
Robert McKee

4
Ponadto, ponieważ niektóre błędy powodują przerwanie wsadu (niektóre błędy powodują tylko przerwanie instrukcji), odgrywa on również rolę w wykrywaniu i odzyskiwaniu błędów. Niektóre instrukcje ( CREATE VIEWitp.) Muszą znajdować się we własnej partii.
Robert McKee,

26

GO nie jest instrukcją, jest to separator partii.

Oddzielone bloki GOsą wysyłane przez klienta na serwer w celu przetworzenia, a klient czeka na ich wyniki.

Na przykład, jeśli piszesz

DELETE FROM a
DELETE FROM b
DELETE FROM c

, zostanie wysłane do serwera jako 3zapytanie jednowierszowe .

Jeśli piszesz

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

, zostanie to przesłane do serwera jako 3zapytania jednowierszowe.

GOsama nie trafia na serwer (gra słów nie jest przeznaczona). Jest to słowo zastrzeżone po stronie klienta i jest rozpoznawane tylko przez SSMSi osql.

Jeśli użyjesz niestandardowego narzędzia do wysyłania zapytań, aby wysłać go przez połączenie, serwer nawet go nie rozpozna i wyświetli błąd.


4
Dlaczego w ogóle musisz wsadować?
PositiveGuy

3
Więc wtedy GO oznacza, że ​​wyślij go, a następnie nie uruchamiaj następnej partii, dopóki klient nie otrzyma „OK, ta partia została wykonana i się powiodła”. W zasadzie to robi GO, aby następna partia mogła zostać pomyślnie uruchomiona, a klient wie upewnij się, że partia jest gotowa po stronie serwera.
PositiveGuy

3
@coffeeaddict: w zasadzie tak. Ponadto niektóre instrukcje wymagają, aby były pierwsze w swoich paczkach (np. CREATE SCHEMA); inne wymagają, aby były jedynymi oświadczeniami w swoich partiach (jak SET SHOWPLAN_XML ON)
Quassnoi

19

Wiele poleceń musi znajdować się we własnej partii, na przykład CREATE PROCEDURE

Lub, jeśli dodasz kolumnę do tabeli, powinna znajdować się we własnej partii. Jeśli spróbujesz WYBRAĆ nową kolumnę w tej samej partii, nie powiedzie się, ponieważ w czasie analizy / kompilacji kolumna nie istnieje.

GO jest używane przez narzędzia SQL do rozwiązania tego problemu z jednego skryptu: nie jest to słowo kluczowe SQL i nie jest rozpoznawane przez silnik.

Oto 2 konkretne przykłady codziennego wykorzystania partii.

Edycja: w twoim przykładzie nie potrzebujesz GO ...

Edycja 2, przykład. Nie możesz upuszczać, tworzyć i uprawniać w jednej partii ... nie mniej ważne, gdzie jest koniec procedury składowanej?

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

Czasami zachodzi potrzeba wielokrotnego wykonywania tego samego polecenia lub zestawu poleceń. Może to polegać na wstawieniu lub aktualizacji danych testowych lub obciążeniu serwera w celu przeprowadzenia testów wydajności. Niezależnie od potrzeb, najłatwiejszym sposobem jest skonfigurowanie pętli while i wykonanie kodu, ale w SQL 2005 istnieje jeszcze prostszy sposób na zrobienie tego.

Powiedzmy, że chcesz utworzyć tabelę testową i załadować do niej 1000 rekordów. Możesz wydać następujące polecenie, które uruchomi to samo polecenie 1000 razy:

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

źródło: http://www.mssqltips.com/tip.asp?tip=1216

Poza tym oznacza "koniec" bloku SQL (np. W procedurze składowanej) ... Oznacza to, że ponownie znajdujesz się w stanie "czystym" ... eG: Parametry użyte w instrukcji przed zresetowaniem kodu ( już nie zdefiniowany)


Ok, więc dlaczego potrzebujesz GO. Aby wiedzieć, że tabela została utworzona przed uruchomieniem instrukcji insert? Nadal nie rozumiem.
PositiveGuy

Patrz Sposób, w jaki o tym myślę, jest taki, że jeśli nie mam GO w twoim przykładzie, tabela jest tworzona jako pierwsza, jest tam teraz, więc wkładka powinna działać. Nie rozumiem, do czego służy GO, jeśli utworzyłem tabelę ... jest dostępna do następnego wstawienia, prawda?!?!?!
PositiveGuy

2
@coffeeaddict: no. „partia” jest analizowana i kompilowana za jednym razem. W czasie kompilacji dbo.TEST nie istnieje. Nie
tworzysz

3

Jak wszyscy już powiedzieli, „GO” nie jest częścią T-SQL. „GO” to separator wsadowy w programie SSMS , aplikacji klienckiej używanej do przesyłania zapytań do bazy danych. Oznacza to, że zadeklarowane zmienne i zmienne tabelowe nie zostaną zachowane z kodu przed „GO” do kodu następującego po nim.

W rzeczywistości GO jest po prostu domyślnym słowem używanym przez SSMS. Jeśli chcesz, możesz to zmienić w opcjach. Dla odrobiny zabawy zmień opcję w systemie innej osoby tak, aby jako separator wsadowy używał „SELECT” zamiast „GO”. Wybacz mój okrutny chichot.


1
W tym miejscu należy zwrócić uwagę na poważną kwestię: należy traktować GO tak, jakby było to słowo kluczowe, nawet jeśli nim nie jest. Nie powinieneś też tego zmieniać. Błędy spowodowane ponownym użyciem specjalnych identyfikatorów mogą być bardzo trudne do debugowania.
Jørgen Fogh

@The Dixie Flatline: czy jesteś pewien, że zadeklarowane zmienne nie zostaną zachowane? W MSSQL 2016 otrzymuję błąd „zmienna już zadeklarowana” podczas uruchamiania: deklaruj $ test int; ustaw $ test = 5; wybierz $ test idź; zadeklaruj $ test int; - Zamień $ na <at>, nie można używać wielu <at> w komentarzach SE.
Wouter

0

Służy do dzielenia bloków logicznych. Twój kod jest interpretowany w linii poleceń sql, co wskazuje na następny blok kodu.

Ale może być użyty jako instrukcja rekurencyjna z określoną liczbą.

Próbować:

exec sp_who2  
go 2

Niektóre stwierdzenia muszą być oddzielone przez GO:

use DB
create view thisViewCreationWillFail
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.