GO Dopo ogni istruzione T-SQL


34

Qual è il ragionamento alla base dell'utilizzo dell'istruzione GO dopo ogni istruzione SQL? Comprendo che GO segnala la fine del batch e / o consente la reputazione delle istruzioni, ma quale vantaggio ha dopo averlo utilizzato.

Sono solo curioso perché molta documentazione di Microsoft ecc. Ha iniziato a usarla dopo ogni affermazione o forse ho appena iniziato a notare.

Inoltre, quali sono le migliori pratiche considerate?

Risposte:


51

Prima di rispondere a quando usarlo e perché, è fondamentale capire esattamente cosa GOsia e cosa non lo sia.

La parola chiave GOviene utilizzata da SQL Server Management Studio e SQLCMD per indicare una cosa e una sola cosa: la fine di un batch di istruzioni. In effetti, puoi anche cambiare ciò che usi per terminare i batch con qualcosa di diverso da "GO":

inserisci qui la descrizione dell'immagine

Quella schermata sopra è un'opzione all'interno di SSMS configurabile.

Ma cos'è un lotto ?? Questo riferimento BOL lo dice meglio:

Un batch è un gruppo di una o più istruzioni Transact-SQL inviate contemporaneamente da un'applicazione a SQL Server per l'esecuzione.

Semplice come quella. È solo un modo personalizzato in cui un'applicazione (sì ... un'applicazione) invia istruzioni a SQL Server. Vediamo un esempio dall'aspetto dell'applicazione di questo. Userò PowerShell per imitare ciò che un'applicazione farebbe per inviare istruzioni e batch a SQL Server:

$ConnectionString = "data source = SomeSQLInstance; initial catalog = AdventureWorks2012; trusted_connection = true; application name = BatchTesting;"

try {
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.Connection = $SqlConnection

    # first batch of statements
    #
    $SqlCmd.CommandText = "
        select * from humanresources.department where departmentid = 1;
        select * from humanresources.department where departmentid = 2;
        select * from humanresources.department where departmentid = 3;
        select * from humanresources.department where departmentid = 4;"

    # execute the first batch
    #
    $SqlConnection.Open()
    $SqlCmd.ExecuteNonQuery()
    $SqlConnection.Close()

    # second batch of statements
    #
    $SqlCmd.CommandText = "
        select * from humanresources.department where departmentid = 5;
        select * from humanresources.department where departmentid = 6;
        select * from humanresources.department where departmentid = 7;
        select * from humanresources.department where departmentid = 8;"

    # execute the second batch
    #
    $SqlConnection.Open()
    $SqlCmd.ExecuteNonQuery()
    $SqlConnection.Close()
}
catch {
    $SqlCmd.Dispose()
    $SqlConnection.Dispose()
    Write-Error $_.Exception
}

I commenti lo danno via, ma puoi vedere sopra che stiamo inviando a livello di codice due lotti a SQL Server. Verifichiamolo, comunque. La mia scelta qui è di utilizzare gli eventi estesi:

create event session BatchTesting
on server
add event sqlserver.sql_batch_starting
(
    set
        collect_batch_text = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_batch_completed
(
    set
        collect_batch_text = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_statement_starting
(
    set
        collect_statement = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_statement_completed
(
    set
        collect_statement = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
)
add target package0.event_file
(
    set
        filename = N'<MyXelLocation>\BatchTesting.xel'
);
go

alter event session BatchTesting
on server
state = start;
go

Tutto ciò che questa sessione di XEvents sta facendo è catturare le istruzioni e i batch che si avviano e si completano da un'applicazione denominata "BatchTesting"(se noti la mia stringa di connessione nel mio esempio di codice PowerShell, è un modo rapido per guardare un particolare creatore di eventi usando l'applicazione " name "parametro della stringa di connessione e filtro fuori da quello).

Dopo aver eseguito il codice PowerShell per inviare tali batch ed istruzioni, vedo i seguenti risultati:

inserisci qui la descrizione dell'immagine

Come puoi vedere dallo screenshot, è chiaro come le istruzioni sono suddivise in due diversi lotti, evidente anche con i mezzi che abbiamo usato per chiamare i lotti. E se osserviamo batch_textla prima occorrenza di sql_batch_starting, possiamo vedere tutte le istruzioni incluse in quel batch:

    select * from humanresources.department where departmentid = 1;
    select * from humanresources.department where departmentid = 2;
    select * from humanresources.department where departmentid = 3;
    select * from humanresources.department where departmentid = 4;

Con quella spiegazione di cosa sia un batch, ora arriva la risposta alla tua domanda su quando terminare i batch. Le regole per i batch si trovano su questo riferimento BOL relativo ai batch :

Le istruzioni CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER e CREATE VIEW non possono essere combinate con altre istruzioni in un batch. L'istruzione CREATE deve avviare il batch. Tutte le altre istruzioni che seguono in quel batch verranno interpretate come parte della definizione della prima istruzione CREATE.

Non è possibile modificare una tabella e quindi fare riferimento alle nuove colonne nello stesso batch.

Se un'istruzione EXECUTE è la prima istruzione in un batch, la parola chiave EXECUTE non è richiesta. La parola chiave EXECUTE è obbligatoria se l'istruzione EXECUTE non è la prima istruzione nel batch.

Allo stesso modo, alcuni errori di runtime (errori di compilazione non consentono l'avvio dell'esecuzione di un batch) che si verificano durante un batch possono causare comportamenti diversi: interrompere completamente il batch o continuare il batch e interrompere solo l'istruzione offensiva (quanto sopra link fornisce due esempi davvero validi: un errore di overflow aritmetico, ad esempio, interromperà l'esecuzione del batch, mentre un errore di violazione del vincolo impedirà solo il completamento dell'istruzione corrente ma l'esecuzione del batch continuerà).

Come molte altre cose della nostra professione, tuttavia, le preferenze personali saranno una forza trainante dietro il modo in cui voi come singoli e scrittori di codice T-SQL terminate i batch. Alcune persone solo definire in modo esplicito lotti quando assolutamente devono (vedi sopra per tali requisiti), e altri terminare lotti a livello di codice il 100% del tempo , anche quando sono in esecuzione solo una singola istruzione in una finestra di query in SQL Server Management Studio. La maggior parte delle persone in genere cade da qualche parte nel mezzo di quei due confini. Per quello che vale, i terminatori di istruzioni hanno lo stesso seguito con pochissimi requisiti obbligatori. Una parte importante di tutto questo è lo stile del codice , in cui non viene applicato (in SSMS e SQLCMD).


Forse un commento ingenuo, ma mi sembra che SQL Server avrebbe potuto determinare cosa eseguire in batch (allo stesso modo in cui molte altre ottimizzazioni sono gestite dal motore di database). Ad esempio, usando le regole che hai descritto invece di fare affidamento sull'utente per scriverle, il che può essere soggetto a errori e sembra aggiungere inutili gonfie agli script.
Steve Chambers,

1
@SteveChambers il mio sentimento esattamente. La risposta dice "è così semplice" (Un batch è un gruppo di una o più istruzioni Transact-SQL inviate contemporaneamente da un'applicazione a SQL Server per l'esecuzione.) Ma non lo è. Ci sono combinazioni di istruzioni che potrei provare e inviare in un batch che non riesce. In definitiva, penso che tu abbia bisogno di capire perché e come inviare un batch sia diverso dall'inviare un set di singole dichiarazioni - così ho finalmente contribuito con la mia risposta su questo: stackoverflow.com/a/56370223/3714936 - che parla anche al tuo commento .
youcantryreachingme
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.