Che cos'è un "batch" e perché viene utilizzato GO?


134

Ho letto e letto su MSDN, ecc. Ok, quindi segnala la fine di un batch.

Cosa definisce un batch? Non vedo perché ho bisogno di andare quando sto incollando un sacco di script per essere eseguiti tutti contemporaneamente.

Non ho mai capito GO. Qualcuno può spiegarlo meglio e quando devo usarlo (dopo quante o che tipo di transazioni)?

Ad esempio, perché dovrei aver bisogno di GO dopo ogni aggiornamento qui:

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

 GO

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


FWIW, sembra che goanche reimposti / cancelli declare @foole dichiarazioni delle variabili - ti stavo facendo venire bisogno di dichiarare errori @foo , fino a quando non ho commentato il go.
JL Peyret,

Risposte:


107

GOnon è correttamente un comando TSQL.

Invece è un comando per il programma client specifico che si collega a un server SQL (Sybase o Microsoft - non sono sicuro di ciò che fa Oracle), segnalando al programma client che l'insieme di comandi che sono stati inseriti fino a quando non è necessario da inviare al server da eseguire.

Perché / quando ne hai bisogno?

  • GO in MS SQL Server ha un parametro "count", quindi puoi usarlo come scorciatoia "ripeti N volte".

  • Aggiornamenti di dimensioni eccessive potrebbero riempire il registro del server SQL. Per evitarlo, potrebbe essere necessario separarli in lotti più piccoli tramite go.

    Nel tuo esempio, se l'aggiornamento per un set di codici Paese ha un volume tale da esaurire lo spazio del registro, la soluzione è quella di separare ciascun codice Paese in una transazione separata, che può essere effettuata separandoli sul client con go.

  • Alcune istruzioni SQL DEVONO essere separate da GO dalle seguenti per funzionare.

    Ad esempio, non è possibile eliminare una tabella e ricreare la tabella con lo stesso nome in una singola transazione, almeno in Sybase (idem per la creazione di procedure / trigger):

> 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
L'istruzione GO non crea transazione. Se includi più istruzioni GO in un'istruzione BEGIN TRANSACTION e alla fine eseguirai un ROLLBACK, eseguirà il rollback di tutti i GO. E se in un GO nel mezzo otterrai qualche errore, e alla fine farai COMMIT, tutti i GO senza errori verranno commessi. È un po 'complicato.
TZ,

7
GOnon "crea una transazione per te". Se non si esegue una transazione esplicita, ogni istruzione creerà comunque la propria transazione. È completamente ortogonale. Se si desidera dividere un aggiornamento più grande in passaggi più piccoli, è comunque possibile farlo in un singolo batch come nel WHILE @@ROWCOUNT > 0modello comune .
Martin Smith,

3
Se non si esegue in una transazione esplicita poi UPDATE T1 SET X =2;UPDATE T1 SET X =2;verrà eseguito come due operazioni distinte in ogni caso . L'aggiunta di non GOfa assolutamente alcuna differenza. E allo stesso modo se si sta eseguendo in una transazione esplicita si estende lotti e ancora una volta GO non fa alcuna differenza.
Martin Smith,

4
Proprio come il chiarimento per chiunque legga questo in seguito ... non GOha assolutamente nulla a che fare con le transazioni e rende le risposte secondo punto sulle transazioni e le dimensioni di un file di registro errate. GOnon avrà alcun effetto. La prima e la terza risposta sono corrette. Inoltre, ci sono momenti in cui è necessario separare le istruzioni in batch separati, ad esempio non è possibile aggiungere una colonna a una tabella e quindi utilizzare quella colonna in un secondo momento nello stesso batch. (continua)
Robert McKee,

4
Inoltre, poiché alcuni errori interromperanno un batch (alcuni errori interrompono solo un'istruzione), svolge anche un ruolo nel rilevamento e nel recupero degli errori. E alcune dichiarazioni ( CREATE VIEW, ecc.) Devono essere nel loro gruppo.
Robert McKee,

26

GO non è un'affermazione, è un separatore batch.

I blocchi separati da GOvengono inviati dal client al server per l'elaborazione e il client attende i loro risultati.

Ad esempio, se scrivi

DELETE FROM a
DELETE FROM b
DELETE FROM c

, questo verrà inviato al server come una 3query a riga singola .

Se scrivi

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

, questo verrà inviato al server come 3query a una riga.

GOstesso non va al server (nessun gioco di parole previsto). È una parola riservata lato client pura ed è riconosciuta solo da SSMSe osql.

Se utilizzerai uno strumento di query personalizzato per inviarlo tramite la connessione, il server non lo riconoscerà nemmeno e genererà un errore.


4
Perché devi fare il batch a tutti ??
Positivo

3
Quindi GO significa inviarlo e quindi non eseguire il batch successivo fino a quando il client non riceve "OK, quel batch è stato eseguito e ha avuto successo" fondamentalmente è ciò che fa GO in modo che il batch successivo possa essere eseguito correttamente e il client lo sappia per assicurarsi che il batch prima sia eseguito sul lato server.
Positivo

3
@coffeeaddict: sostanzialmente sì. Inoltre, alcune dichiarazioni richiedono di essere le prime nei loro lotti (come CREATE SCHEMA); altri richiedono di essere le uniche dichiarazioni nei loro lotti (come SET SHOWPLAN_XML ON)
Quassnoi,

19

Molti comandi devono essere nel proprio batch, come CREATE PROCEDURE

In alternativa, se si aggiunge una colonna a una tabella, questa dovrebbe trovarsi nel proprio batch. Se si tenta di SELEZIONARE la nuova colonna nello stesso batch, l'operazione non riesce perché al momento dell'analisi / compilazione la colonna non esiste.

GO viene utilizzato dagli strumenti SQL per risolverlo da uno script: non è una parola chiave SQL e non viene riconosciuto dal motore.

Questi sono 2 esempi concreti di utilizzo quotidiano dei lotti.

Modifica: nel tuo esempio, non hai bisogno di GO ...

Modifica 2, esempio. Non puoi rilasciare, creare e autorizzare in un batch ... non ultimo, dov'è la fine della procedura memorizzata?

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

A volte è necessario eseguire ripetutamente lo stesso comando o insieme di comandi. Questo potrebbe essere quello di inserire o aggiornare i dati del test o caricare il server sul test delle prestazioni. Qualunque sia la necessità, il modo più semplice per farlo è impostare un ciclo while ed eseguire il codice, ma in SQL 2005 esiste un modo ancora più semplice per farlo.

Supponiamo che tu voglia creare una tabella di test e caricarla con 1000 record. È possibile emettere il comando seguente e verrà eseguito lo stesso comando 1000 volte:

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

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

Oltre a ciò segna la "fine" di un blocco SQL (ad es. In una procedura memorizzata) ... Significa che si è di nuovo su uno stato "pulito" ... eG: parametri utilizzati nell'istruzione prima che il codice venga resettato ( non più definito)


Ok, allora perché hai bisogno di GO. In modo che tu sappia che la tabella è stata creata prima dell'esecuzione dell'istruzione insert? Ancora non capisco.
Positivo

Vedi Il modo in cui penso a questo, è che se non ho GO nel tuo esempio, la tabella viene creata per prima, è lì ora, quindi l'inserto dovrebbe funzionare. Non capisco a cosa serva GO se ho creato la tabella ... è disponibile per il prossimo inserto, vero?!?!?!
Positivo

2
@coffeeaddict: no. il "batch" viene analizzato e compilato in una volta sola. Al momento della compilazione, dbo.TEST non esiste. Non stai istanziando un oggetto e SQL non è un codice procedurale riga per riga
gbn

3

Come già detto da tutti, "GO" non fa parte di T-SQL. "GO" è un separatore batch in SSMS , un'applicazione client utilizzata per inviare query al database. Ciò significa che le variabili dichiarate e le variabili di tabella non persistono dal codice prima di "GO" al codice che lo segue.

In effetti, GO è semplicemente la parola predefinita utilizzata da SSMS. Questo può essere modificato nelle opzioni se lo si desidera. Per un po 'di divertimento, cambia l'opzione sul sistema di qualcun altro per usare "SELEZIONA" come un separatore batch anziché "GO". Perdona la mia risata crudele.


1
C'è in realtà un punto serio da chiarire qui: dovresti trattare GO come se fosse una parola chiave, anche se non lo è. Inoltre non dovresti mai cambiarlo. I bug causati dal riutilizzo di identificatori speciali possono essere molto difficili da eseguire il debug.
Jørgen Fogh,

@ La Dixie Flatline: sei sicuro che le variabili dichiarate non persistano? In MSSQL 2016 ottengo un errore "variabile già dichiarata" durante l'esecuzione: declare $ test int; impostare $ test = 5; selezionare $ test go; dichiarare $ test int; - Sostituisci $ con <at>, non puoi usare più <at> nei commenti SE.
Wouter,

0

È usato per dividere i blocchi logici. Il tuo codice viene interpretato nella riga di comando sql e questo indica il prossimo blocco di codice.

Ma potrebbe essere usato come istruzione ricorsiva con un numero specifico.

Provare:

exec sp_who2  
go 2

Alcune dichiarazioni devono essere delimitate da GO:

use DB
create view thisViewCreationWillFail
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.