Ну, идентификаторы всегда Unicode / NVARCHAR
, так что технически вы не можете создать ничего, что не имеет имени Unicode 🙃.
Проблема, с которой вы здесь столкнулись, полностью связана с классификацией используемых символов. Правила для обычных (то есть не разделенных) идентификаторов:
- Первая буква должна быть:
- Буква в соответствии со стандартом Unicode 3.2.
- подчеркивание (_), знак (@) или знак числа (#)
- Последующие письма могут быть:
- Буквы, определенные в стандарте Unicode 3.2.
- Десятичные числа из базовой латиницы или других национальных сценариев.
- подчеркивание (_), знак (@), знак числа (#) или знак доллара ($)
- Встроенные пробелы или специальные символы не допускаются.
- Дополнительные символы не допускаются.
Я выделил единственные правила, которые имеют значение в этом контексте. Причина, по которой правила «первой буквы» здесь не актуальны, заключается в том, что первая буква во всех локальных переменных и параметрах всегда является знаком «at» @
.
И чтобы быть ясным: то, что считается «буквой», а то, что считается «десятичной цифрой», основано на свойствах, которые присваиваются каждому символу в базе данных символов Unicode. Юникод присваивает каждому символу множество свойств, таких как: is_uppercase, is_lowercase, is_digit, is_decimal, is_combining и т. Д. И т. Д. Это не вопрос того, что мы, смертные, будем считать буквами или десятичными цифрами, но каким символам были назначены эти свойства. Эти свойства часто используются в регулярных выражениях для сопоставления с «пунктуацией» и т. Д. Например, \p{Lu}
сопоставление с любой заглавной буквой (для всех языков / сценариев) и \p{IsDingbats}
сопоставление с любым символом «дингбаты».
Итак, в вашей попытке сделать:
DECLARE @¯\_(ツ)_/¯ INT;
только символы _
(подчеркивание или " ツ
нижняя строка") и (буква Katakana Tu U + 30C4) соответствуют этим правилам. Теперь все символы в ¯\_(ツ)_/¯
порядке для идентификаторов с разделителями, но, к сожалению, кажется, что имена переменных / параметров и GOTO
метки не могут быть разделены (хотя имена курсоров могут быть).
Таким образом, для имен переменных / параметров, поскольку они не могут быть разделены, вы застряли с использованием только символов, которые квалифицируются как «буквы» или «десятичные цифры» в Unicode 3.2 (ну, согласно документации; мне нужно проверить если классификации были обновлены для более новых версий Unicode, поскольку классификации обрабатываются не так, как веса сортировки).
ОДНАКО , вещи не так просты, как должны быть. Теперь я смог завершить свое исследование и обнаружил, что указанное определение не совсем правильно. Точное (и проверяемое) определение того, какие символы действительны для обычных идентификаторов:
Первый персонаж:
- Может быть чем-то, что в Unicode 3.2 классифицировано как «ID_Start» (которое включает в себя «буквы», но также «буквенно-цифровые символы»)
- Может быть
_
( _
нижняя строка / подчеркивание) или (нижняя строка полной ширины)
- Может быть
@
, но только для переменных / параметров
- Может быть
#
, но если объект привязан к схеме, то только для таблиц и хранимых процедур (в этом случае они указывают, что объект является временным)
Последующие персонажи:
- Может быть чем-то, что в Unicode 3.2 классифицируется как «ID_Continue» (которое включает в себя «десятичные» числа, а также «пробелы и непересекающиеся знаки объединения» и «соединительные знаки препинания»)
- Может быть
@
, #
или$
- Может быть любым из 26 символов, классифицированных в Unicode 3.2 как символы управления форматом
(забавный факт: «ID» в «ID_Start» и «ID_Continue» означает «Идентификатор». Представьте себе, что ;-)
Согласно «Утилиты Юникод: 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».
В следующих двух записях блога подробно описаны шаги, предпринятые для поиска точного списка символов, включая ссылки на сценарии импорта:
- Uni-Code: Поиск истинного списка допустимых символов для регулярных идентификаторов T-SQL, часть 1
- Uni-Code: Поиск истинного списка допустимых символов для регулярных идентификаторов T-SQL, часть 2
Наконец, для тех, кто просто хочет увидеть список и не интересуется, что нужно для его обнаружения и проверки, вы можете найти его здесь:
Полностью полный список допустимых символов идентификатора T-SQL
(пожалуйста, дайте странице время для загрузки; это 3,5 МБ и почти 47 000 строк)
Относительно «действительных» символов 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
которое является "?" (try:), SELECT CHAR(63);
поскольку этот символ, даже если с префиксом в верхнем регистре "N", определенно отсутствует в кодовой странице 1252. Однако этот символ находится в корейской кодовой странице и дает правильный результат, даже без "N" "префикс в базе данных с сопоставлением по-корейски по умолчанию:
SELECT UNICODE('ツ'); -- 12484
Что касается первой буквы, влияющей на результат: это невозможно, поскольку первая буква для локальных переменных и параметров всегда @
. Первая буква, которую мы получаем для контроля над этими именами, на самом деле является вторым символом имени.
Относительно того, почему имена локальных переменных, имена параметров и GOTO
метки не могут быть разделены: я подозреваю, что это связано с тем, что эти элементы являются частью самого языка, а не тем, что попадает в системную таблицу в качестве данных.
Я не думаю, что это Unicode вызывает проблему; в случае имен локальных переменных или параметров это означает, что символ не является допустимым символом ASCII / Unicode 3.2 (и не существует какой-либо экранирующей последовательности для переменных / параметров, как для других типов сущностей).
Этот пакет работает нормально, он использует символ Unicode, который просто не нарушает правила для не разделенных идентификаторов:
Как только вы пытаетесь использовать косую черту или тире, оба из которых являются действительными символами ASCII, он бомбит:
В документации не указывается, почему эти идентификаторы подчиняются правилам, немного отличающимся от всех других идентификаторов, или почему они не могут быть экранированы, как другие.
источник
@
имеет имя var / param. Любой из символов, которые не работают, не должен работать ни в одной позиции, даже если ему предшествуют допустимые символы. 2) в документе указано только то, что дополнительные символы не могут использоваться в обычных идентификаторах (что, похоже, имеет место для всего, что я пробовал), но не накладывает ограничений на идентификаторы с разделителями, как во встроенных пробелах. Кроме того, я считаю, что они разные, потому что они являются частью языка T-SQL, а не вещами в БД.GOTO
метки допускают разделение, то единственным ограничением будет длина. Я могу только предположить, что анализ и / или обработка этих нескольких элементов происходит на другом уровне или имеет некоторые другие ограничения, которые сделали невозможным использование значений с разделителями. По крайней мере, я надеюсь, что это не было произволом или недосмотром.is_alphabetic
илиnumeric_type=decimal
.