web-dev-qa-db-fra.com

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

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

Alors, quand devrais-je l'utiliser?

203
Anwar Pinto

Depuis un SQLServerCentral.Com article par Ken Powers:

Le point-virgule

Le 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 était possible de coder T-SQL pendant des années sans jamais rencontrer de point-virgule.

Utilisation

Il existe deux situations dans lesquelles vous devez utiliser le point-virgule. Dans le premier cas, vous utilisez une expression de table commune (CTE), et le CTE n'est pas la première instruction du lot. La deuxième étape consiste à émettre une instruction Service Broker et que l'instruction Service Broker ne soit pas la première instruction du lot.

141
TheTXI

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

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

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

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

Avec certains compilateurs C, il est possible d’annuler le retour principal, même si la norme impose à main de retourner int. Mais cela rend notre code et nous-mêmes moins portables.

La plus grande difficulté de la programmation n’est pas d’apprendre de nouvelles choses, mais d’apprendre de mauvaises habitudes. Dans la mesure où nous pouvons éviter au départ d’acquérir de mauvaises habitudes, c’est une victoire pour nous, pour notre code et pour tous ceux qui lisent ou utilisent notre code.

73
tpdi

Dans SQL2008 BOL, ils indiquent que dans les prochaines versions, des points-virgules seront nécessaires. Par conséquent, utilisez-le toujours.

Référence:

24
GSerg

Si je le lis correctement, il sera nécessaire d’utiliser des points-virgules pour mettre fin aux 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 formaterait votre script et ajouterait les points-virgules. Je pense qu'il est toujours en version bêta cependant ...

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

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

22
Spidermain50

Vous devez l'utiliser.

L'utilisation d'un point-virgule pour terminer des instructions est standard et constitue en fait une exigence dans plusieurs autres plates-formes de base de données. SQL Server n’utilise le point-virgule que dans des cas particuliers, mais dans les cas où un point-virgule n’est pas requis, son utilisation ne pose aucun problème. Je vous recommande vivement d’adopter la pratique consistant à mettre fin à toutes les déclarations par un point-virgule. Cela améliorera non seulement la lisibilité de votre code, mais pourra également vous éviter des problèmes. (Lorsqu'un point-virgule est requis et qu'il 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 le fait de ne pas terminer les instructions T-SQL par un point-virgule est une fonctionnalité obsolète. Cela signifie que l'objectif à long terme est de renforcer 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 si cela n’est pas nécessaire pour le moment.

Source: Principes fondamentaux de T-SQL de Microsoft SQL Server 2012 par Itzik Ben-Gan.


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

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

enter image description here

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

enter image description here

17
gotqn

Opinion personnelle: Utilisez-les uniquement là où ils sont requis. (Voir la réponse de TheTXI ci-dessus pour la liste requise.)

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

[Cet avis est spécifique à SQL Server. D'autres bases de données peuvent avoir des exigences plus strictes. Si vous écrivez du SQL pour s'exécuter sur plusieurs bases de données, vos exigences peuvent varier.]

tpdi a déclaré ci-dessus, "dans un script, comme vous envoyez plus d'une déclaration, vous en avez besoin." C'est en fait pas correct. Tu n'as pas besoin d'eux.

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

Sortie:

Semicolons are optional
Semicolons are optional
Semicolons are optional
Semicolons are optional
9
Rob Garrison

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

Une fois que la transaction a fonctionné comme je le souhaitais, j'ai décidé de mettre un dispositif d’essai en place afin que toute erreur éventuelle soit annulée. Ce n’est qu’après cette opération que la transaction n’a pas été validée (SSMS le confirme lorsqu’il tente de fermer la fenêtre avec un message Nice vous avertissant du fait qu’il existe 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 a fallu

COMMIT TRANSACTION;

Notez qu'aucune erreur ni aucun avertissement n'est fourni et que rien n'indique que la transaction est toujours non validée avant la tentative de fermeture de 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 (de syntaxe ou autre) n’ayant été signalée, il n’était pas évident de cerner le problème.

A l'inverse, ROLLBACK TRANSACTION semble fonctionner aussi bien dans le bloc BEGIN CATCH avec ou sans point-virgule.

Cela peut sembler logique, mais cela semble arbitraire et Alice-in-Wonderland-ish.

3
Matthew Davidian

Il semble que les points-virgules ne doivent pas être utilisés avec les opérations de curseur: OPEN, FETCH, CLOSE et DEALLOCATE. Je viens de perdre quelques heures avec ça. J'ai jeté un coup d'œil au BOL et j'ai remarqué que [;] n'était pas indiqué dans la syntaxe de ces instructions de curseur !!

Alors j'ai eu:

OPEN mycursor;

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

Mais:

OPEN mycursor

travaillé.

3
rab

Selon 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 de cette version de SQL Server, il le sera dans une version ultérieure.

(voir aussi le commentaire de @gerryLowry)

2
Alan B

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

voir ici

0
Nick V

Si vous aimez avoir des erreurs aléatoires Délai d'attente de la commande 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 bogue, mais cela se produit et j'ai appris cela d'une expérience amère.

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

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

0
Allan Maher

Note: Ceci répond à la question telle qu'elle est écrite, mais pas au problème énoncé. L'ajouter ici, car les gens le rechercheront

Le point-virgule est également utilisé avant WITH dans 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 générera un CTE appelé Numbers constitué d’entiers [1..10]. Cela se fait en créant une table avec la valeur 1 uniquement, puis en récursant jusqu'à atteindre 10.

0
v010dya

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;

résultats

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

résultats

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

(1 row(s) affected)
0
John Feild