Analyser le littéral de nombre SQL Server avec un soulignement

Je me request pourquoi cela fonctionne et pourquoi il ne renvoie pas une erreur:

SELECT 2015_11 

Résultat:

 ╔══════╗ ║ _11 ║ ╠══════╣ ║ 2015 ║ ╚══════╝ 

Deuxième cas:

 SELECT 2.1_a ╔═════╗ ║ _a ║ ╠═════╣ ║ 2.1 ║ ╚═════╝ 

Vérification des métadonnées:

 SELECT name, system_type_name FROM sys.dm_exec_describe_first_result_set( N'SELECT 2015_11', NULL, 0) UNION ALL SELECT name, system_type_name FROM sys.dm_exec_describe_first_result_set( N'SELECT 3.2_a', NULL, 0) ╔══════╦══════════════════╗ ║ name ║ system_type_name ║ ╠══════╬══════════════════╣ ║ _11 ║ int ║ ║ _a ║ numeric(2,1) ║ ╚══════╩══════════════════╝ 

Alors que l'identifiant qui commence par la lettre se comporte comme je pense qu'il devrait:

 SELECT a_11 -- Invalid column name 'a_11'. 

LiveDemo

SQL traite la requête comme

 SELECT 2015_11 

comme

 SELECT 2015 _11 

qui est raccourci pour

 SELECT 2015 AS [_11] 

SQL Server s'attend à ce que les noms de colonne suivent certaines règles de convention de dénomination telles que détaillées dans ce lien MSDN

Les noms des variables, des fonctions et des procédures stockées doivent être conforms aux règles suivantes pour les identificateurs Transact-SQL. Le premier caractère doit être l'un des suivants:

  1. Une lettre telle que définie par la norme Unicode 3.2. La définition Unicode des lettres inclut les caractères latins d'un z à l'autre, de A à Z, ainsi que les caractères littéraux d'autres langues.
  2. Le trait de soulignement (_), au signe (@) ou au signe dièse (#).

    Certains symboles au début d'un identificateur ont une signification particulière dans SQL Server. Un identifiant normal qui commence par le signe arobase indique toujours une variable ou un paramètre local et ne peut pas être utilisé comme nom d'un autre type d'object. Un identifiant qui commence par un signe numérique indique une table ou une procédure temporaire. Un identifiant qui commence par deux signes numériques (##) indique un object temporaire global. Bien que les caractères de signe de nombre ou double signe peuvent être utilisés pour commencer les noms d'autres types d'objects, nous ne recommandons pas cette pratique.

Certaines fonctions Transact-SQL ont des noms qui commencent par double au niveau des signes (@@). Pour éviter toute confusion avec ces fonctions, vous ne devez pas utiliser les noms commençant par @@.

La syntaxe pour SELECT selon MSDN est également similaire à

SELECT [TOUS | DISTINCT] [TOP (expression) [PERCENT] [AVEC TIES]] :: = {* | {nom_table | nom_vue | table_alias}. * | {[{nom_table | nom_vue | table_alias}. ] {nom_colonne | $ IDENTITÉ | $ ROWGUID} | udt_column_name [{. | ::} {{nom_propriété | nom_zone} | nom_méthode (argument [, … n])}] | expression [[AS] alias_colonne]} | column_alias = expression} [, … n]

Dans ce cas, l'parsingur SQL vérifie d'abord le nom de la table, puis le nom de la colonne, Identity et rowguid, et ainsi de suite jusqu'à ce qu'il atteigne la correspondance avec

| expression [[AS] alias_colonne]

Il lit ensuite la valeur littérale jusqu'à souligner le caractère qui est quand il se rend count que le littéral doit avoir fini et commence à parsingr les caractères suivants comme Column_alias sans AS aussi explicite.

Pour vérifier cela, essayez le code suivant dans le server SQL

 SELECT 2015AS _11 

Cela produira les mêmes résultats que

 SELECT 2015_11 

Aussi pour vérifier ce que je viens d'écrire ci-dessus voir la capture d'écran de SSMS qui fait un code mettant en évidence sur AS

entrez la description de l'image ici

Dans votre premier exemple, 2015 est un littéral entier et dans le deuxième exemple 2.1 est un littéral décimal

Dans votre troisième exemple, a n'est pas un littéral valide. Si tu essayes

 SELECT 'a'_8 

Cela vous donnera des résultats comme

 ╔═════╗ ║ _8 ║ ╠═════╣ ║ a ║ ╚═════╝ 

PS : Vous verrez que cela fonctionne à peu près de la même manière avec # aussi

Donc, SELECT 2015#11 donnera des résultats similaires

 ╔══════╗ ║ #11 ║ ╠══════╣ ║ 2015 ║ ╚══════╝ 

Pour comprendre ce qui se passe, vous devez comprendre ce que SQL Server accepte comme identifiants. Il y a beaucoup de règles qui sont documentées ici . Mais, l'important est:

Le premier caractère doit être l'un des suivants:

  1. Une lettre telle que définie par la norme Unicode 3.2. La définition Unicode des lettres inclut les caractères latins d'un z à l'autre, de A à Z, ainsi que les caractères littéraux d'autres langues.

  2. Le trait de soulignement (_), au signe (@) ou au signe dièse (#).

Le point important est que lorsque l'parsingur SQL Server rencontre un chiffre, il se dit: "Ceci est un nombre". Quand il frappe le trait de soulignement, il dit "Eh bien, pas plus de nombre, doit commencer quelque chose d'autre". L'parsingur reconnaît le deuxième composant comme un identificateur valide, donc ceci est traité comme:

 select 2015 _11 

qui est pour un alias de colonne, même sans as .