GO après chaque instruction T-SQL

34

Quel est le raisonnement derrière l'utilisation de l'instruction GO après chaque instruction SQL? Je comprends que GO indique la fin du lot et / ou autorise la réputation des déclarations, mais quel avantage at-il à l’utiliser après chaque déclaration?

Je suis simplement curieux de constater que de nombreux documents Microsoft, etc., ont commencé à être utilisés après chaque déclaration ou que je viens tout juste de commencer à le remarquer.

Aussi, qu'est-ce qui est considéré comme la meilleure pratique?

L'idiot
la source

Réponses:

51

Avant de répondre quand et pourquoi l'utiliser, il est d'abord primordial de comprendre exactement ce qui GOest et ce qui ne l'est pas.

Le mot GO- clé est utilisé par SQL Server Management Studio et SQLCMD afin de signifier une chose et une seule chose: La fin d'un lot d'instructions. En fait, vous pouvez même changer ce que vous utilisez pour terminer les lots par autre chose que "GO":

entrez la description de l'image ici

La capture d'écran ci-dessus est une option configurable dans SSMS.

Mais qu'est-ce qu'un lot ?? Cette référence de BOL le dit le mieux:

Un lot est un groupe d'une ou plusieurs instructions Transact-SQL envoyées simultanément d'une application à SQL Server pour exécution.

Aussi simple que cela. C'est simplement une manière personnalisée qu'une application (oui ... une application) envoie des instructions à SQL Server. Voyons un exemple d'application ressemblant à cela. J'utiliserai PowerShell pour imiter ce qu'une application ferait pour envoyer des instructions et des lots à 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
}

Les commentaires l'indiquent, mais vous pouvez voir ci-dessus que nous envoyons deux lots par programme à SQL Server. Vérifions cela, cependant. Mon choix ici est d'utiliser les événements étendus:

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

Tout ce que la session XEvents fait consiste à capturer les instructions et les lots qui commencent et se terminent à partir d’une application nommée "BatchTesting"(si vous remarquez la chaîne de connexion dans mon exemple de code PowerShell, c’est un moyen rapide de regarder un créateur d’événements en utilisant l’application nom "paramètre de chaîne de connexion et filtrage de celui-ci).

Après avoir exécuté le code PowerShell pour envoyer ces lots et instructions, les résultats suivants sont visibles:

entrez la description de l'image ici

Comme vous pouvez le voir sur la capture d'écran, il est clair que les déclarations sont divisées en deux lots différents, ce qui est également évident par le moyen que nous utilisions auparavant pour appeler les lots. Et si nous regardons dans la batch_textpremière occurrence de sql_batch_starting, nous pouvons voir toutes les instructions incluses dans ce lot:

    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;

Avec cette explication de ce qu'est un lot, voici maintenant la réponse à votre question de savoir quand mettre fin aux lots. Les règles relatives aux lots se trouvent dans cette référence BOL concernant les lots :

Les instructions CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER et CREATE VIEW ne peuvent pas être combinées avec d'autres instructions d'un lot. L'instruction CREATE doit démarrer le lot. Toutes les autres instructions qui suivent dans ce lot seront interprétées comme faisant partie de la définition de la première instruction CREATE.

Une table ne peut pas être modifiée, puis les nouvelles colonnes référencées dans le même lot.

Si une instruction EXECUTE est la première instruction d'un lot, le mot clé EXECUTE n'est pas requis. Le mot clé EXECUTE est requis si l'instruction EXECUTE n'est pas la première instruction du lot.

De même, certaines erreurs d’exécution (les erreurs de compilation ne permettent pas l’exécution d’un lot) qui se produisent au cours d’un lot peuvent entraîner différents comportements: annuler totalement le lot, ou continuer le lot et abandonner uniquement l’instruction incriminée link donne deux très bons exemples: une erreur de dépassement arithmétique, par exemple, arrêtera l'exécution du lot, tandis qu'une erreur de violation de contrainte empêchera seulement l'exécution de l'instruction en cours mais le traitement continuera à s'exécuter).

Comme beaucoup de choses dans notre profession, cependant, les préférences personnelles seront un facteur déterminant de la manière dont vous terminez les lots en tant qu'individu et rédacteur de code T-SQL. Certaines personnes définissent explicitement les lots uniquement lorsqu'elles en ont absolument besoin (voir ci-dessus pour ces exigences), tandis que d' autres terminent les lots par programmation 100% du temps , même lorsqu'elles n'exécutent qu'une seule instruction dans une fenêtre de requête dans SSMS. La plupart des gens se situent généralement au milieu de ces deux limites. Pour ce que cela vaut, les terminateurs d'instructions ont le même suivi avec également très peu d'exigences imposées. Une grande partie de tout cela est le style de code , où il n'est pas appliqué (dans SSMS et SQLCMD).

Thomas Stringer
la source
C'est peut-être un commentaire naïf, mais il me semble que SQL Server aurait pu déterminer lui-même ce qu'il faut exécuter par lots (de la même manière que de nombreuses autres optimisations sont gérées par le moteur de base de données). Par exemple, en utilisant les règles que vous avez décrites plutôt que de compter sur l'utilisateur pour les écrire, ce qui peut être sujet à des erreurs et semble ajouter une surcharge inutile aux scripts.
Steve Chambers
1
@SteveChambers mon sentiment exactement. La réponse dit "c'est aussi simple que cela" (Un lot est un groupe d'une ou plusieurs instructions Transact-SQL envoyées simultanément d'une application à SQL Server pour exécution.) Mais ce n'est pas le cas. Il y a des combinaisons d'instructions que je pourrais essayer et envoyer dans un lot qui échoue. En fin de compte, je pense que vous devez comprendre pourquoi et en quoi l' envoi d'un lot est différent de l'envoi d'un ensemble de déclarations individuelles. J'ai donc finalement apporté ma propre réponse à cette question: stackoverflow.com/a/56370223/3714936 - qui rejoint également votre commentaire. .
Youcantryreachingme