Eh bien, les identifiants sont toujours Unicode / NVARCHAR
, donc techniquement, vous ne pouvez rien créer sans nom Unicode.
Le problème que vous rencontrez ici est entièrement dû à la classification du ou des personnage (s) utilisé (s). Les règles pour les identifiants normaux (c'est-à-dire non délimités) sont les suivantes:
- La première lettre doit être:
- Une lettre telle que définie par la norme Unicode 3.2.
- trait de soulignement (_), au signe (@) ou au chiffre (#)
- Les lettres suivantes peuvent être:
- Lettres telles que définies dans la norme Unicode 3.2.
- Nombres décimaux issus du Basic Latin ou d’autres scripts nationaux.
- trait de soulignement (_), arobase (@), chiffre (#) ou dollar ($)
- Les espaces incorporés ou les caractères spéciaux ne sont pas autorisés.
- Les caractères supplémentaires ne sont pas autorisés.
J'ai mis en gras les seules règles importantes dans ce contexte. La raison pour laquelle les règles de "première lettre" ne sont pas pertinentes ici est que la première lettre de toutes les variables et de tous les paramètres locaux est toujours le "at sign" @
.
Et pour être clair: ce qui est considéré comme une "lettre" et ce qui est considéré comme un "chiffre décimal" est basé sur les propriétés que chaque caractère est assigné dans la base de données de caractères Unicode. Unicode attribue de nombreuses propriétés à chaque caractère, telles que: is_uppercase, is_lowercase, is_digit, is_decimal, is_combining, etc. Cela ne dépend pas de ce que nous, mortels, considérons comme des lettres ou des chiffres décimaux, mais des caractères qui ont été affectés à ces propriétés. Ces propriétés sont souvent utilisées dans les expressions rationnelles pour faire correspondre la "ponctuation", etc. Par exemple, \p{Lu}
correspond à toute lettre majuscule (dans toutes les langues / tous les scripts) et \p{IsDingbats}
correspond à tout caractère "Dingbats".
Donc, dans votre tentative de faire:
DECLARE @¯\_(ツ)_/¯ INT;
seuls les _
caractères (trait de soulignement ou "ligne inférieure") et ツ
(lettre Katakana Tu U + 30C4) entrent dans ces règles. Désormais, tous les caractères ¯\_(ツ)_/¯
entrant conviennent aux identificateurs délimités, mais malheureusement, il semble que les noms de variable / paramètre et les GOTO
étiquettes ne puissent pas être délimités (bien que les noms de curseur puissent l'être).
Ainsi, pour les noms de variable / paramètre, car ils ne peuvent pas être délimités, vous ne pouvez utiliser que des caractères qualifiés de "lettres" ou de "chiffres décimaux" à partir d'Unicode 3.2 (enfin, d'après la documentation; j'ai besoin de tester si les classifications ont été mises à jour pour les versions plus récentes d'Unicode, car les classifications sont traitées différemment des poids de tri).
CEPENDANT # 1 , les choses ne sont pas aussi simples qu'elles devraient l'être. Je suis maintenant en mesure d'achever mes recherches et de constater que la définition indiquée n'est pas tout à fait correcte. La définition précise (et vérifiable) des caractères valides pour les identificateurs habituels est la suivante:
Premier personnage:
- Peut être n'importe quoi classé dans Unicode 3.2 comme "ID_Start" (qui inclut "des lettres" mais aussi des "caractères numériques semblables à des lettres")
- Peut être
_
(ligne basse / trait de soulignement) ou _
(ligne basse pleine largeur)
- Peut être
@
, mais seulement pour les variables / paramètres
- Peut être
#
, mais s'il s'agit d'un objet lié au schéma, alors uniquement pour les tables et les procédures stockées (dans ce cas, ils indiquent que l'objet est temporaire)
Caractères suivants:
- Peut être n'importe quoi classé dans Unicode 3.2 en tant que "ID_Continue" (qui inclut des nombres "décimaux", mais aussi "des marques de combinaison d'espacement et de non-remise", et "des signes de ponctuation")
- Peut - être
@
, #
ou$
- Peut être n'importe lequel des 26 caractères classés dans Unicode 3.2 en tant que caractères de contrôle de format
(Fait amusant: "ID" dans "ID_Start" et "ID_Continue" signifie "Identifier". Imaginez cela ;-)
Selon "Utilitaires Unicode: UnicodeSet":
Caractères de départ valides
[: Age = 3.2:] & [: ID_Start = Oui:]
-- Test one "Letter" from each of 10+ languages, as of Unicode 3.2
DECLARE @ᔠᑥᑒᏯשፙᇏᆇᄳᄈლဪඤaൌgೋӁウﺲﶨ INT;
-- works
-- Test a Supplementary Character that is a "Letter" as of Unicode 3.2
DECLARE @𝒲 INT;-- Mathematical Script Capital W (U+1D4B2)
/*
Msg 102, Level 15, State 1, Line XXXXX
Incorrect syntax near '0xd835'.
*/
Caractères de continuation valides
[: Age = 3.2:] & [: ID_Continue = Yes:]
-- Test various decimal numbers, but none are Supplementary Characters
DECLARE @६৮༦൯௫୫9 INT;
-- works (including some Hebrew and Arabic, which are right-to-left languages)
-- Test a Supplementary Character that is a "decimal" number as of Unicode 3.2
DECLARE @𝟜 INT; -- MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR (U+1D7DC)
/*
Msg 102, Level 15, State 1, Line XXXXX
Incorrect syntax near '0xd835'.
*/
-- D835 is the first character in the surrogate pair D835 DFDC that makes up U+1D7DC
CEPENDANT N ° 2 , même la recherche dans la base de données Unicode peut être aussi simple. Ces deux recherches produisent une liste de caractères valides pour ces catégorisations, et ces caractères proviennent de Unicode 3.2, MAIS les définitions des différentes catégorisations changent d'une version à l'autre du standard Unicode. Cela signifie que la définition de "ID_Start" dans Unicode v 10.0 (ce que la recherche utilise aujourd'hui, 2018-03-26) n'est pas ce qu'elle était dans Unicode v 3.2. La recherche en ligne ne peut donc pas fournir une liste exacte. Mais vous pouvez récupérer les fichiers de données Unicode 3.2 et récupérer la liste des caractères "ID_Start" et "ID_Continue" à partir de là pour les comparer à ce que SQL Server utilise réellement. Et j’ai fait cela et confirmé une correspondance exacte avec les règles que j’ai énoncées ci-dessus dans «CEPENDANT N ° 1».
Les deux articles de blog suivants décrivent en détail les étapes à suivre pour trouver la liste exacte des caractères, y compris des liens vers les scripts d'importation:
- Uni-code: recherche de la liste vraie de caractères valides pour les identificateurs standard T-SQL, partie 1
- Uni-code: recherche de la liste vraie de caractères valides pour les identificateurs standard T-SQL, partie 2
Enfin, pour tous ceux qui veulent seulement voir la liste et ne sont pas concernés par ce qu'il a fallu pour le découvrir et le vérifier, vous pouvez le trouver ici:
Liste complète des caractères d'identification T-SQL valides
(donnez à la page un moment de chargement; 3,5 Mo et presque 47 000 lignes)
Concernant les caractères ASCII "valides", tels que /
et -
, ne fonctionne pas: le problème n'a rien à voir avec le fait que les caractères sont également définis ou non dans le jeu de caractères ASCII. Pour être valide, le caractère doit avoir soit la ID_Start
ou des ID_Continue
biens, ou être l' un des rares personnages personnalisés notés séparément. Il existe de nombreux caractères ASCII "valides" (62 sur un total de 128 - principalement des caractères de ponctuation et de contrôle) qui ne sont pas valides dans les identifiants "normaux".
Concernant les caractères supplémentaires: bien qu’ils puissent certainement être utilisés dans des identifiants délimités (et la documentation ne semble pas indiquer le contraire), s’il est vrai qu’ils ne peuvent pas être utilisés dans des identifiants classiques, c’est probablement parce qu’ils ne sont pas entièrement pris en charge. Les fonctions intégrées antérieures aux classements supplémentaires axés sur les caractères ont été introduites dans SQL Server 2012 (elles sont traitées comme deux caractères "inconnus"), et elles ne peuvent même pas être différenciées les unes des autres dans des classements non binaires antérieurs à la centaine. niveau Collations (introduit dans SQL Server 2008).
En ce qui concerne ASCII: les codages à 8 bits ne sont pas utilisés ici car tous les identifiants sont Unicode / NVARCHAR
/ UTF-16 LE. L'instruction SELECT ASCII('ツ');
retourne une valeur 63
qui est un "?" (try:) SELECT CHAR(63);
puisque ce caractère, même s’il est précédé d’un "N" majuscule, n’est certainement pas dans la page de code 1252. Cependant, ce caractère se trouve dans la page de code coréenne et produit le résultat correct, même sans le "N". "préfixe, dans une base de données avec un classement coréen par défaut:
SELECT UNICODE('ツ'); -- 12484
Concernant la première lettre affectant le résultat: cela n’est pas possible car la première lettre pour les variables et paramètres locaux l’est toujours @
. La première lettre que nous contrôlons pour ces noms est en fait le deuxième caractère du nom.
En ce qui concerne les raisons pour lesquelles les noms de variables locales, les noms de paramètres et les GOTO
étiquettes ne peuvent pas être délimités: je suppose que cela est dû au fait que ces éléments font partie du langage lui-même et ne sont pas des éléments qui se retrouveront dans une table système sous forme de données.
Je ne pense pas que c'est le Unicode qui cause le problème; dans le cas des noms de variables ou de paramètres locaux, le caractère n'est pas un caractère ASCII / Unicode 3.2 valide (et il n'y a pas de séquence d'échappement pour les variables / paramètres comme il en existe pour les autres types d'entité).
Ce lot fonctionne correctement, il utilise un caractère Unicode qui n'enfreint tout simplement pas les règles applicables aux identificateurs non délimités:
Dès que vous essayez d'utiliser une barre oblique ou un tiret, qui sont tous les deux des caractères ASCII valides, le programme explose:
La documentation n'indique pas pourquoi ces identifiants sont soumis à des règles légèrement différentes de celles de tous les autres identifiants, ni pourquoi ils ne peuvent pas être échappés comme les autres.
la source
@
du var / param. Tous les caractères qui ne fonctionnent pas ne devraient fonctionner dans aucune position, même s'ils sont précédés de caractères valides. 2) la doc indique seulement que les caractères supplémentaires ne peuvent pas être utilisés dans les identifiants habituels (ce qui semble être le cas pour tout ce que j'ai essayé), mais n'impose aucune restriction aux identifiants délimités, comme pour les espaces incorporés. De plus, je pense que ce sont différentes parce qu'elles font partie du langage T-SQL et non de la DB.GOTO
étiquettes permettaient d'être délimités, la seule restriction serait la longueur. Je ne peux que supposer que l'analyse et / ou la gestion de ces quelques éléments se produisent à un niveau différent ou ont d'autres contraintes qui rendent impossible l'utilisation de valeurs délimitées. Au moins j'espère que ce n'était pas arbitraire ou un oubli.is_alphabetic
ounumeric_type=decimal
.