web-dev-qa-db-fra.com

GO après chaque instruction T-SQL

Quel est le raisonnement derrière l'utilisation de l'instruction GO après chaque instruction SQL? Je comprends que GO signale la fin du lot et/ou permet la réputation des relevés mais quel avantage a-t-il à les utiliser après chaque relevé.

Je suis simplement curieux car beaucoup de documentation Microsoft etc. ont commencé à l'utiliser après chaque déclaration ou peut-être que je viens de commencer à le remarquer.

Qu'est-ce qui est considéré comme la meilleure pratique?

34
TheIdiot

Avant de répondre quand l'utiliser et pourquoi, il est primordial de comprendre exactement ce qu'est GO , et ce qu'il n'est pas.

Le mot clé GO est utilisé par SQL Server Management Studio et SQLCMD pour signifier une chose et une seule: 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":

enter image description here

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

Mais qu'est-ce qu'un lot ?? Cette référence 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 juste une manière personnalisée qu'une application (oui ... une application) envoie des instructions à SQL Server. Voyons un exemple d'application de 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 le révèlent, mais vous pouvez voir ci-dessus que nous envoyons par programme deux lots à SQL Server. Vérifions cela, cependant. Mon choix ici est d'utiliser des é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

La session XEvents ne fait que capturer les instructions et les lots qui démarrent et se terminent à partir d'une application nommée "BatchTesting" (si vous remarquez ma chaîne de connexion dans mon exemple de code PowerShell, c'est un moyen rapide de regarder un auteur particulier d'événements en utilisant le paramètre de chaîne de connexion "nom d'application" et en filtrant cela).

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

enter image description here

Comme vous pouvez le voir sur la capture d'écran, il est clair comment les instructions sont divisées en deux lots différents, également évident par les moyens que nous avons utilisés pour appeler les lots. Et si nous regardons dans le batch_text de la premiè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 quoi un lot est, voici maintenant la réponse à votre question de quand pour terminer les lots. Les règles pour les lots se trouvent sur 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 de démarrer l'exécution d'un lot) qui se produisent pendant un lot peuvent entraîner différents comportements: abandonner totalement le lot, ou continuer le lot et annuler uniquement l'instruction incriminée (ce qui précède) lien 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 uniquement l'instruction en cours de se terminer mais le lot continuera à s'exécuter).

Comme beaucoup de choses dans notre profession, cependant, la préférence personnelle sera une énorme force motrice derrière la façon dont vous, en tant qu'individu et auteur de code T-SQL, terminez les lots . Certaines personnes ne définissent explicitement les lots que lorsqu'elles doivent absolument (voir ci-dessus pour ces exigences), et les autres terminent les lots par programmation 100% du temps, même lorsqu'ils 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 quelque part au milieu de ces deux frontières. Pour ce que ça 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).

51
Thomas Stringer