Ну, ідентифікатори завжди є Unicode / NVARCHAR
, тому технічно ви не можете створити нічого, що не має імені Unicode 🙃.
Проблема, яка виникає тут, повністю пов'язана з класифікацією символів, які використовуються. Правила для звичайних (тобто не обмежених) ідентифікаторів:
- Перший лист повинен бути:
- Лист, визначений стандартом Unicode 3.2.
- підкреслення (_), знак (@) або знак цифри (#)
- Наступні листи можуть бути:
- Букви, як визначено у стандарті Unicode 3.2.
- Десяткові числа з базової латини або інших національних сценаріїв.
- підкреслення (_), знак (@), цифра (#) або знак долара ($)
- Вбудовані пробіли або спеціальні символи заборонені.
- Додаткові символи заборонені.
Я виділив жир єдиними правилами, які мають значення в цьому контексті. Причина того, що правила "Першої літери" тут не доречні, полягає в тому, що перша буква у всіх локальних змінних та параметрах завжди є "в знаку" @
.
І щоб було зрозуміло: те, що вважається "літерою", а що вважається "десятковою цифрою", ґрунтується на властивостях, які кожному символу присвоєно в базі даних символів Unicode. Unicode призначає кожному символу багато властивостей, таких як: is_uppercase, is_lowercase, is_digit, is_decimal, is_combining тощо, тощо. Це не питання про те, що ми, смертні, вважатимемо літерами чи десятковими цифрами, але яким символам було призначено ці властивості. Ці властивості часто використовуються в регулярних виразах для відповідності "пунктуації" тощо. Наприклад, \p{Lu}
відповідає будь-якій великій літері (для всіх мов / сценаріїв) та \p{IsDingbats}
відповідає будь-якому символу "Дінгбати".
Отже, у вашій спробі зробити:
DECLARE @¯\_(ツ)_/¯ INT;
у ці правила вписуються лише _
символи (підкреслення або "низька лінія") та ツ
(літера Катакани Tu U + 30C4). Тепер усі символи ¯\_(ツ)_/¯
вказують на розмежовані ідентифікатори, але, на жаль, схоже, що імена змінних / параметрів та GOTO
міток не можна обмежувати (хоча імена курсорів можуть бути).
Отже, для імен змінних / параметрів, оскільки вони не можуть бути розмежовані, ви затримуєтесь лише тим, що використовуєте символи, які вважаються або "буквами", або "десятковими цифрами", як Unicode 3.2 (ну, згідно з документацією; мені потрібно перевірити якщо класифікації оновлено для новіших версій Unicode, оскільки класифікація обробляється інакше, ніж ваги сортування).
ЯКЩО №1 , все не так прямо, як має бути. Зараз я зміг завершити своє дослідження і виявив, що викладене визначення не зовсім правильне. Точне (і перевіряемое) визначення символів, дійсних для звичайних ідентифікаторів:
Перший персонаж:
- У Unicode 3.2 може бути що-небудь класифіковане як "ID_Start" (що включає "Літери", але також "буквені цифрові символи")
- Це може бути
_
(низька лінія / підкреслення) або _
(низька лінія повної ширини)
- Може бути
@
, але тільки для змінних / параметрів
- Може бути
#
, але якщо об'єкт пов'язаний із схемою, то лише для таблиць і збережених процедур (у такому випадку вони вказують, що об'єкт тимчасовий)
Наступні символи:
- У Unicode 3.2 може бути що-небудь класифіковане як "ID_Continue" (що включає "десяткові" числа, але також "інтервал та нерозміщення комбінуючих знаків" та "з'єднання розділових знаків")
- Може бути
@
, #
або$
- Може бути будь-який з 26 символів, класифікованих в Unicode 3.2 як символи керування форматом
(цікавий факт: "ID" в "ID_Start" та "ID_Continue" означає "Ідентифікатор". Уявіть, що ;-)
Відповідно до "Утиліти Unicode: UnicodeSet":
Дійсні початкові символи
[: Вік = 3.2:] & [: ID_Start = Так:]
-- 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'.
*/
Дійсні символи продовження
[: Вік = 3.2:] & [: ID_Continue = Так:]
-- 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
ЗАРАЗ № 2 , навіть не пошук бази даних Unicode може бути таким простим. Ці два пошукові записи створюють список дійсних символів для цих категоризацій, і ці символи походять з Unicode 3.2, АЛЕ визначення різних категоризацій змінюється у версіях стандарту Unicode. Значення, визначення "ID_Start" в Unicode v 10.0 (для чого використовується цей пошук сьогодні, 2018-03-26) - це не те, що було в Unicode v 3.2. Отже, онлайн-пошук не може надати точного списку. Але ви можете захопити файли даних Unicode 3.2 та схопити список символів "ID_Start" та "ID_Continue", щоб порівняти з тим, що насправді використовує SQL Server. І я це зробив і підтвердив точну відповідність правилам, про які я говорив вище, у "ТАКОЖ №1".
У наступних двох публікаціях блогу детально описані кроки для пошуку точного списку символів, включаючи посилання на сценарії імпорту:
- Уні-код: Пошук справжнього списку дійсних символів для регулярних ідентифікаторів T-SQL, частина 1
- Уні-код: Пошук справжнього списку дійсних символів для регулярних ідентифікаторів T-SQL, частина 2
Нарешті, для тих, хто просто хоче переглянути список і не переймається тим, що потрібно для його виявлення та перевірки, можна знайти це тут:
Повноцінний список дійсних символів ідентифікаторів T-SQL
(будь-ласка, надайте сторінці момент для завантаження; це 3,5 Мб і майже 47 к рядків)
Що стосується "дійсних" символів ASCII, таких як /
і -
не працюють: питання не має нічого спільного з тим, чи визначені символи також у наборі символів ASCII. Щоб бути дійсним, персонаж повинен мати ID_Start
або ID_Continue
властивість, або властивість, або бути одним з небагатьох спеціальних символів, зазначених окремо. Існує досить багато "дійсних" символів ASCII (62 із 128 загальних знаків - переважно пунктуаційні та контрольні символи), які не дійсні в "Регулярних" ідентифікаторах.
Щодо додаткових символів: хоча вони, безумовно, можуть бути використані в обмежених ідентифікаторах (а документація, схоже, не вказує інакше), якщо це правда, що вони не можуть бути використані в звичайних ідентифікаторах, це, швидше за все, через їх повну підтримку вбудовані функції до допоміжних символів-зібрань, введених у SQL Server 2012 (вони розглядаються як два окремі "невідомі" символи), і їх не можна було навіть відрізнити один від одного у небінарних зіставленнях до початку 100- зіставлення рівня (впроваджено в SQL Server 2008).
Щодо ASCII: тут не використовуються 8-бітні кодування, оскільки всі ідентифікатори - це Unicode / NVARCHAR
/ UTF-16 LE. Оператор SELECT ASCII('ツ');
повертає значення, 63
яке є "?" (спробуйте:), SELECT CHAR(63);
оскільки цього символу, навіть якщо він є префіксом великого регістру "N", звичайно, немає у коді сторінки 1252. Однак цей символ знаходиться на Корейській сторінці Кореї, і він дає правильний результат навіть без "N "префікс у базі даних з корейським зіставленням за замовчуванням:
SELECT UNICODE('ツ'); -- 12484
Щодо першої літери, що впливає на результат: це неможливо, оскільки перша буква для локальних змінних та параметрів є завжди @
. Перша літера, яку ми отримуємо для контролю над цими іменами, - це насправді 2-й символ імені.
Що стосується того, чому імена локальних змінних, назви параметрів та GOTO
міток не можна обмежувати: я підозрюю, що це пов'язано з тим, що ці елементи є частиною самої мови, а не тим, що знайде свій шлях до системної таблиці як даних.