Quand dois-je utiliser des points-virgules dans SQL Server?

221

En vérifiant du code sur le Web et des scripts générés par SQL Server Management Studio, j'ai remarqué que certaines instructions se terminent par un point-virgule.

Alors, quand dois-je l'utiliser?

Anwar Pinto
la source
23
SQL Server 2008 R2 msdn.microsoft.com/en-us/library/ms177563.aspx "Conventions de syntaxe Transact-SQL (Transact-SQL)" ; == Terminateur d'instruction Transact-SQL. Bien que le point-virgule ne soit pas requis pour la plupart des instructions dans cette version de SQL Server, il le sera dans une future version .
gerryLowry
2
Bien qu'ils prétendent qu'un point-virgule sera requis dans une future version, cela ne se réalisera jamais. Ils ne peuvent jamais exiger cela pour des raisons de compatibilité. Cela briserait environ 100% des demandes.
usr
1
Nous sommes maintenant en 2019 et aucun point-virgule n'est toujours accepté avec joie dans la dernière version de SQL Server. Comme le dit @usr, à moins que Microsoft ne veuille faire une pause 100% propre, il n'y a aucun moyen de le faire appliquer.
Ian Kemp

Réponses:

152

À partir d'un article SQLServerCentral.Com de Ken Powers:

Le point-virgule

Le caractère point-virgule est un terminateur d'instruction. Il fait partie de la norme ANSI SQL-92, mais n'a jamais été utilisé dans Transact-SQL. En effet, il a été possible de coder T-SQL pendant des années sans jamais rencontrer de point-virgule.

Usage

Il existe deux situations dans lesquelles vous devez utiliser le point-virgule. La première situation est celle où vous utilisez une expression de table commune (CTE), et le CTE n'est pas la première instruction du lot. La seconde est l'endroit où vous émettez une instruction Service Broker et l'instruction Service Broker n'est pas la première instruction du lot.

TheTXI
la source
9
Est-ce THROWune déclaration Service Broker? Nous devons inclure un point-virgule avant un lancer dans cet exemple:BEGIN ;THROW @Error, 'Invalid FundingID', 2; RETURN END
Chris Walsh
1
Il semble qu'ils encouragent fondamentalement l'utilisation du point-virgule en général, en l'exigeant avant tous les nouveaux types d'instructions introduits ces dernières années. ( MERGEtrop par exemple). Comme mentionné dans d'autres réponses, dans la norme ANSI, ils sont requis
Mark Sowul
2
@maurocam Je pense que vous avez mal lu le document. Si vous regardez ce lien, il indique " Ne pas terminer les instructions Transact-SQL par un point-virgule". est obsolète.
Caltor
Comme je le vois, cela ne répond pas vraiment à la question de savoir quand on doit (par opposition à must ) un point - virgule.
Stewart
81

Par défaut, les instructions SQL se terminent par des points-virgules. Vous utilisez un point-virgule pour terminer les instructions, sauf si vous avez (rarement) défini un nouveau terminateur d'instruction.

Si vous n'envoyez qu'une seule instruction, techniquement, vous pouvez vous passer du terminateur d'instruction; dans un script, comme vous envoyez plusieurs déclarations, vous en avez besoin.

En pratique, incluez toujours le terminateur même si vous n'envoyez qu'une seule instruction à la base de données.

Edit: en réponse à ceux qui disent que les terminateurs d'instructions ne sont pas requis par [SGBDR particulier], bien que cela puisse être vrai, ils sont requis par la norme SQL ANSI. Dans toute programmation, si nous pouvons adhérer à une norme sans perte de fonctionnalité, nous devrions le faire, car alors ni notre code ni nos habitudes ne sont liés à un seul fournisseur propriétaire.

Avec certains compilateurs C, il est possible d'avoir void de retour principal, même si le standard exige que main retourne int. Mais cela rend notre code et nous-mêmes moins portables.

La plus grande difficulté de la programmation efficace n'est pas d'apprendre de nouvelles choses, c'est de désapprendre de mauvaises habitudes. Dans la mesure où nous pouvons éviter d'acquérir de mauvaises habitudes en premier lieu, c'est une victoire pour nous, pour notre code et pour quiconque lit ou utilise notre code.

tpdi
la source
25

Vous devez l' utiliser.

La pratique consistant à utiliser un point-virgule pour terminer des instructions est standard et est en fait une exigence dans plusieurs autres plates-formes de base de données. SQL Server requiert le point-virgule uniquement dans des cas particuliers, mais dans les cas où un point-virgule n'est pas requis, son utilisation ne pose pas de problème. Je vous recommande vivement d'adopter la pratique de terminer toutes les instructions par un point-virgule. Non seulement cela améliorera la lisibilité de votre code, mais dans certains cas, cela peut vous éviter des ennuis. (Lorsqu'un point-virgule est requis et n'est pas spécifié, le message d'erreur généré par SQL Server n'est pas toujours très clair.)

Et le plus important:

La documentation de SQL Server indique que la non-terminaison des instructions T-SQL par un point-virgule est une fonctionnalité obsolète. Cela signifie que l'objectif à long terme est d'imposer l'utilisation du point-virgule dans une future version du produit. C'est une raison de plus pour prendre l'habitude de mettre fin à toutes vos déclarations, même là où elles ne sont actuellement pas requises.

Source: Microsoft SQL Server 2012 T-SQL Fundamentals par Itzik Ben-Gan.


Un exemple de pourquoi vous devez toujours utiliser ;sont les deux requêtes suivantes (copiées à partir de ce message ):

BEGIN TRY
    BEGIN TRAN
    SELECT 1/0 AS CauseAnException
    COMMIT
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE()
    THROW
END CATCH

entrez la description de l'image ici

BEGIN TRY
    BEGIN TRAN
    SELECT 1/0 AS CauseAnException;
    COMMIT
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE();
    THROW
END CATCH

entrez la description de l'image ici

gotqn
la source
7
Cela semble être un argument fort que vous devez utiliser (points - virgules sauvegardés par les guillemets), mais seulement un seul cas où il y a un must .
Gregor Thomas
3
@Gregor, s'il est annoncé que l'utilisation de points-virgules est une not using themtechnique incontournable et déconseillée, vous devez les utiliser. Sinon, il y a un risque de souffrir à l'avenir. Si vous ne prévoyez pas de mettre à niveau / changer de travail et que vous allez toujours travailler avec SQL Server 2000, vous êtes en sécurité :-)
gotqn
5
Droit, devrait , je suis d' accord. Mais la première ligne de votre réponse met l'accent sur le must , ce qui n'est pas le cas - du moins pas encore.
Gregor Thomas
2
L'exemple avec des points-virgules se traduit par Incorrect syntax near 'THROW'.SQL Server 2008 (10.0.6241.0), qui est la version que je dois gérer au travail. Cela fonctionne comme indiqué en 2012. J'ai été convaincu de commencer à utiliser des points-virgules à cause de la dépréciation. Je ne pense pas que ce serait un problème en 2008 la plupart du temps.
Pilot_51
1
Votre réponse est de loin la meilleure! Il mérite bien plus de votes positifs.
Stewart
22

Si je lis correctement, il sera nécessaire d'utiliser des points-virgules pour terminer les instructions TSQL. http://msdn.microsoft.com/en-us/library/ms143729%28v=sql.120%29.aspx

EDIT: J'ai trouvé un plug-in pour SSMS 2008R2 qui formatera votre script et ajoutera les points-virgules. Je pense que c'est toujours en version bêta ...

http://www.tsqltidy.com/tsqltidySSMSAddin.aspx

EDIT: J'ai trouvé un outil / plugin gratuit encore meilleur appelé ApexSQL ... http://www.apexsql.com/

Spidermain50
la source
11

Opinion personnelle: utilisez-les uniquement là où elles sont nécessaires. (Voir la réponse de TheTXI ci-dessus pour la liste requise.)

Comme le compilateur n'en a pas besoin, vous pouvez mettre partout, mais pourquoi? Le compilateur ne vous dira pas où vous en avez oublié un, vous vous retrouverez donc avec une utilisation incohérente.

[Cette opinion est spécifique à SQL Server. D'autres bases de données peuvent avoir des exigences plus strictes. Si vous écrivez SQL pour qu'il s'exécute sur plusieurs bases de données, vos besoins peuvent varier.]

tpdi a déclaré ci-dessus, "dans un script, comme vous envoyez plusieurs déclarations, vous en avez besoin." Ce n'est en fait pas correct. Vous n'en avez pas besoin.

PRINT 'Semicolons are optional'
PRINT 'Semicolons are optional'
PRINT 'Semicolons are optional';
PRINT 'Semicolons are optional';

Production:

Semicolons are optional
Semicolons are optional
Semicolons are optional
Semicolons are optional
Rob Garrison
la source
1
Que pensez-vous de cette discussion? sqlservercentral.com/Forums/Topic636549-8-1.aspx (vous pouvez utiliser [email protected]: bugmenot si vous n'avez pas de compte)
Anwar Pinto
2
J'apprécie que vous ayez déclaré clairement que ce n'est que votre opinion, mais je ne pense pas que cela soit une bonne réponse car cela entre en conflit avec la documentation Microsoft et la norme ANSI. Je pense que cette opinion serait meilleure dans un commentaire. (
N'essayant pas de vous dénigrer
4

J'ai encore beaucoup à apprendre sur T-SQL, mais en travaillant sur du code pour une transaction (et en basant le code sur des exemples de stackoverflow et d'autres sites), j'ai trouvé un cas où il semble qu'un point-virgule soit requis et s'il est manquant, l'instruction ne semble pas du tout s'exécuter et aucune erreur n'est générée. Cela ne semble être couvert dans aucune des réponses ci-dessus. (Il s'agissait de MS SQL Server 2012.)

Une fois que la transaction a fonctionné comme je le souhaitais, j'ai décidé de faire un essai sur elle, donc s'il y a des erreurs, elle est annulée. Ce n'est qu'après cela que la transaction n'a pas été validée (SSMS le confirme en essayant de fermer la fenêtre avec un joli message vous alertant du fait qu'il y a une transaction non validée.

Donc ça

COMMIT TRANSACTION 

en dehors d'un bloc BEGIN TRY / END TRY a bien fonctionné pour valider la transaction, mais à l'intérieur du bloc, il devait être

COMMIT TRANSACTION;

Notez qu'aucune erreur ou avertissement n'est fourni et aucune indication que la transaction n'est toujours pas validée jusqu'à ce que vous tentiez de fermer l'onglet de requête.

Heureusement, cela cause un problème si énorme qu'il est immédiatement évident qu'il y a un problème. Malheureusement, aucune erreur (syntaxe ou autre) n'ayant été signalée, le problème n'était pas immédiatement évident.

Au contraire, ROLLBACK TRANSACTION semble fonctionner aussi bien dans le bloc BEGIN CATCH avec ou sans point-virgule.

Il peut y avoir une certaine logique à cela, mais cela semble arbitraire et Alice-au-Pays des Merveilles.

Matthew Davidian
la source
Une cause possible de ceci est qu'il COMMIT TRANSACTIONaccepte un nom de point de transaction / sauvegarde facultatif (qu'il ignorera). Sans point-virgule de fin, COMMIT TRANSACTIONpeut manger le symbole suivant s'il est analysé comme identifiant, ce qui peut changer radicalement la sémantique du code. Si cela entraîne une erreur, le CATCHpeut se déclencher sans COMMITjamais avoir été exécuté. Inversement, tout en ROLLBACK TRANSACTIONacceptant également un identifiant facultatif comme celui-ci, une erreur d'analyse est susceptible d'entraîner l'annulation de la transaction de toute façon.
Jeroen Mostert
3

Il semble que des points - virgules ne doivent pas être utilisés conjointement avec des opérations de curseur: OPEN, FETCH, CLOSEetDEALLOCATE . Je viens de perdre quelques heures avec ça. J'ai examiné de près le BOL et j'ai remarqué que [;] n'est pas affiché dans la syntaxe de ces instructions de curseur !!

J'ai donc eu:

OPEN mycursor;

et cela m'a donné l'erreur 16916.

Mais:

OPEN mycursor

travaillé.

rab
la source
2
Je ne pense pas que ce soit correct. Le BOL n'est pas très cohérent en mentionnant le point-virgule sur la syntaxe de l'instruction, jetez un œil au SELECT par exemple. De plus, j'ai vu OPEN someCursor; fonctionne bien, même pour FETCH, CLOSE et DEALLOCATE ...
Valentino Vranken
Cela me suggère un bug avec l'analyseur. Quelle version de SQL Server utilisez-vous / utilisiez-vous?
Stewart
2

Selon les conventions de syntaxe Transact-SQL (Transact-SQL) (MSDN)

Terminateur d'instruction Transact-SQL. Bien que le point-virgule ne soit pas requis pour la plupart des instructions dans cette version de SQL Server, il le sera dans une future version.

(voir aussi le commentaire de @gerryLowry)

Alan B
la source
0

Lorsque vous utilisez une instruction DISABLE ou ENABLE TRIGGER dans un lot qui contient d'autres instructions, l'instruction juste avant de se terminer par un point-virgule. Sinon, vous obtiendrez une erreur de syntaxe. J'ai arraché mes cheveux avec celui-ci ... Et après, je suis tombé sur cet article MS Connect à propos de la même chose. Il est fermé car il ne sera pas réparé.

voir ici

Nick V
la source
0

Remarque: cela répond à la question telle qu'elle est écrite, mais pas au problème comme indiqué. L'ajouter ici, car les gens le chercheront

Le point-virgule est également utilisé auparavant WITHdans les instructions CTE récursives:

;WITH Numbers AS
(
    SELECT n = 1
    UNION ALL
    SELECT n + 1
    FROM Numbers
    WHERE n+1 <= 10
)
SELECT n
FROM Numbers

Cette requête va générer un CTE appelé Numbers qui se compose d'entiers [1..10]. Pour ce faire, créez une table avec la valeur 1 uniquement, puis récursive jusqu'à ce que vous atteigniez 10.

v010dya
la source
8
Techniquement, pas «avant avec», mais après tout ce qui précède. Si avec est la première instruction du lot, aucun point-virgule n'est requis.
Tor Haugen
Il n'est pas non plus utilisé auparavant avec WITH. Ce n'est que le point-virgule qui termine l'instruction précédente. Il semble que certaines personnes aient décidé que le point-virgule devrait être ici car il s'agit d'un scénario dans lequel ledit point-virgule est requis. Pourquoi ces gens ont décidé que c'était mieux que de toujours terminer les instructions par des points-virgules, je n'en ai aucune idée.
Stewart
0

Si vous aimez obtenir des erreurs de délai d'attente de commande aléatoires dans SQLServer, laissez le point-virgule à la fin de vos chaînes CommandText.

Je ne sais pas si cela est documenté n'importe où ou s'il s'agit d'un bug, mais cela se produit et je l'ai appris d'une expérience amère.

J'ai des exemples vérifiables et reproductibles utilisant SQLServer 2008.

aka -> En pratique, incluez toujours le terminateur même si vous n'envoyez qu'une seule instruction à la base de données.

Allan Maher
la source
Si vous obtenez des délais d'expiration pour une requête basée sur rien d'autre que sur l'existence ou non d'un point-virgule à la fin, cela est presque certainement dû à des plans d'exécution différents, car ceux-ci sont mis en cache en faisant correspondre le texte exact de la requête, y compris autrement sémantiquement non pertinent des choses comme des espaces, des commentaires et un point-virgule de fin. Le point-virgule lui-même sera entièrement innocent de causer des problèmes de timing, cependant.
Jeroen Mostert
-2

Les points-virgules ne fonctionnent pas toujours dans les instructions SELECT composées.

Comparez ces deux versions différentes d'une instruction SELECT composée triviale.

Le code

DECLARE @Test varchar(35); 
SELECT @Test=
    (SELECT 
        (SELECT 
            (SELECT 'Semicolons do not always work fine.';););); 
SELECT @Test Test;

Retour

Msg 102, Level 15, State 1, Line 5
Incorrect syntax near ';'.

Cependant, le code

DECLARE @Test varchar(35)
SELECT @Test=
    (SELECT 
        (SELECT 
            (SELECT 'Semicolons do not always work fine.'))) 
SELECT @Test Test

Retour

Test
-----------------------------------
Semicolons do not always work fine.

(1 row(s) affected)
John Feild
la source
11
[Un an plus tard]: Wow, je suis surpris, personne n'a encore commenté cette réponse! Bien sûr, cela ne fonctionnera pas, les points-virgules sont des séparateurs d'instructions, donc votre code avec les points-virgules est: 1- SELECT @ Test = (SELECT (SELECT (SELECT (Les points-virgules ne fonctionnent pas toujours bien.); - ce n'est pas un correct déclaration 2-); - ni l'un ni l'autre n'est ce 3-); - ni celui-là 4-); - ni celui-là, le point-virgule doit être après les 3 parenthèses
PhpLou
1
Vous utilisez uniquement des points-virgules pour terminer les instructions . Une sous-requête n'est pas une instruction. Les instructions sont des choses qui sont exécutées en séquence. Dans votre exemple, il existe trois instructions: 1. DECLARE @ Test varchar (35) 2. SELECT @ Test = (SELECT (SELECT (SELECT 'Les points-virgules ne fonctionnent pas toujours bien.'))) 3. SELECT @ Test Test
Stewart