Nun, Bezeichner sind immer Unicode / NVARCHAR
. Technisch gesehen können Sie also nichts erstellen, das keinen Unicode-Namen hat 🙃.
Das Problem, das Sie hier haben, ist ausschließlich auf die Klassifizierung der verwendeten Zeichen zurückzuführen. Die Regeln für reguläre (dh nicht begrenzte) Bezeichner sind:
- Der erste Buchstabe muss sein:
- Ein Buchstabe gemäß Unicode-Standard 3.2.
- Unterstrich (_), am Zeichen (@) oder Nummernzeichen (#)
- Nachfolgende Buchstaben können sein:
- Buchstaben wie im Unicode-Standard 3.2 definiert.
- Dezimalzahlen aus einfachen lateinischen oder anderen nationalen Schriften.
- Unterstrich (_), am Zeichen (@), Nummernzeichen (#) oder Dollarzeichen ($)
- Eingebettete Leerzeichen oder Sonderzeichen sind nicht zulässig.
- Ergänzungszeichen sind nicht erlaubt.
Ich habe die einzigen Regeln herausgearbeitet, die in diesem Zusammenhang von Bedeutung sind. Der Grund dafür, dass die Regeln für den "Anfangsbuchstaben" hier nicht relevant sind, ist, dass der Anfangsbuchstabe in allen lokalen Variablen und Parametern immer das "Vorzeichen" ist @
.
Und um es klar auszudrücken: Was als "Buchstabe" und was als "Dezimalstelle" gilt, basiert auf den Eigenschaften , die jedem Zeichen in der Unicode-Zeichendatenbank zugewiesen sind. Unicode weist jedem Zeichen viele Eigenschaften zu, z. B. is_uppercase, is_lowercase, is_digit, is_decimal, is_combining usw. Dies ist keine Frage dessen, was wir Sterblichen als Buchstaben oder Dezimalstellen betrachten, sondern welchen Zeichen diese Eigenschaften zugewiesen wurden. Diese Eigenschaften werden häufig in regulären Ausdrücken verwendet, um eine Übereinstimmung mit "Interpunktion" usw. zu erzielen. Sie entsprechen beispielsweise \p{Lu}
einem Großbuchstaben (in allen Sprachen / Skripten) und einem \p{IsDingbats}
beliebigen "Dingbats" -Zeichen.
Also, in Ihrem Versuch zu tun:
DECLARE @¯\_(ツ)_/¯ INT;
Nur die Zeichen _
(Unterstrich oder "niedrige Linie") und ツ
(Katakana Letter Tu U + 30C4) passen in diese Regeln. Nun sind alle Zeichen in ¯\_(ツ)_/¯
für durch Trennzeichen getrennte Bezeichner in Ordnung, aber es scheint leider, dass Variablen- / Parameternamen und GOTO
Bezeichnungen nicht getrennt werden können (obwohl Cursornamen möglich sind).
Bei Variablen- / Parameternamen müssen Sie daher nur Zeichen verwenden, die ab Unicode 3.2 entweder "Buchstaben" oder "Dezimalstellen" sind, da sie nicht voneinander abgegrenzt werden können (entsprechend der Dokumentation; ich muss testen) wenn Klassifizierungen für neuere Versionen von Unicode aktualisiert wurden, da Klassifizierungen anders behandelt werden als Sortiergewichtungen).
JEDOCH # 1 sind die Dinge nicht so einfach, wie sie sein sollten. Ich konnte nun meine Recherchen abschließen und habe festgestellt, dass die angegebene Definition nicht ganz korrekt ist. Die genaue (und überprüfbare) Definition, welche Zeichen für reguläre Bezeichner gültig sind, lautet:
Erstes Zeichen:
- Kann alles sein, was in Unicode 3.2 als "ID_Start" klassifiziert ist (einschließlich "Letters", aber auch "letterlike numeric characters")
- Kann
_
(niedrige Linie / Unterstrich) oder _
(volle Breite niedrige Linie) sein
- Kann sein
@
, aber nur für Variablen / Parameter
- Kann sein
#
, aber wenn schemagebundenes Objekt, dann nur für Tabellen und gespeicherte Prozeduren (in diesem Fall geben sie an, dass das Objekt temporär ist)
Nachfolgende Zeichen:
- Kann alles sein, was in Unicode 3.2 als "ID_Continue" klassifiziert ist (einschließlich "Dezimalzahlen", aber auch "Kombinationszeichen für Abstände und Leerzeichen" und "Interpunktionszeichen verbinden").
- Sein kann
@
, #
oder$
- Kann eines der 26 Zeichen sein, die in Unicode 3.2 als Formatsteuerzeichen klassifiziert sind
(lustige Tatsache: die "ID" in "ID_Start" und "ID_Continue" steht für "Identifier". Stellen Sie sich das vor ;-)
Laut "Unicode Utilities: UnicodeSet":
Gültige Startzeichen
[: Age = 3.2:] & [: ID_Start = Yes:]
-- 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'.
*/
Gültige Fortsetzungszeichen
[: 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
JEDOCH # 2 , nicht einmal das Durchsuchen der Unicode-Datenbank kann so einfach sein. Diese beiden Suchvorgänge führen zu einer Liste gültiger Zeichen für diese Kategorisierungen. Diese Zeichen stammen aus Unicode 3.2, ABER die Definitionen der verschiedenen Kategorisierungen ändern sich in den Versionen des Unicode-Standards. Das heißt, die Definition von "ID_Start" in Unicode 10.0 (was diese Suche heute verwendet, 26.03.2018) entspricht nicht der Definition in Unicode 3.2. Die Online-Suche kann daher keine genaue Liste liefern. Sie können jedoch die Unicode 3.2-Datendateien abrufen und die Liste der Zeichen "ID_Start" und "ID_Continue" abrufen, um zu vergleichen, was SQL Server tatsächlich verwendet. Und ich habe dies getan und eine genaue Übereinstimmung mit den Regeln bestätigt, die ich oben in "JEDOCH # 1" angegeben habe.
In den folgenden beiden Blogeinträgen werden die Schritte zum Ermitteln der genauen Liste der Zeichen einschließlich der Links zu den Importskripten erläutert:
- Der Uni-Code: Die Suche nach der wahren Liste der gültigen Zeichen für reguläre T-SQL-Bezeichner, Teil 1
- Der Uni-Code: Die Suche nach der wahren Liste der gültigen Zeichen für reguläre T-SQL-Bezeichner, Teil 2
Für alle, die die Liste nur sehen möchten und sich nicht mit dem befassen, was für die Ermittlung und Überprüfung erforderlich ist, finden Sie diese Informationen hier:
Vollständig vollständige Liste der gültigen T-SQL-ID-Zeichen
(bitte geben Sie der Seite einen Moment Zeit zum Laden; es sind 3,5 MB und fast 47 KB Zeilen)
In Bezug auf „gültig“ ASCII - Zeichen, wie /
und -
arbeiten, nicht: das Problem hat nichts damit zu tun , ob die Zeichen auch im ASCII - Zeichensatz definiert. Um gültig zu sein, muss der Charakter entweder haben ID_Start
oder das ID_Continue
Eigentum oder eines der wenige benutzerdefinierten Zeichen separat zur Kenntnis genommen. Es gibt einige "gültige" ASCII-Zeichen (62 von insgesamt 128 - meist Interpunktions- und Steuerzeichen), die in "regulären" Bezeichnern nicht gültig sind.
Ergänzende Zeichen: Obwohl sie mit Sicherheit in begrenzten Bezeichnern verwendet werden können (und die Dokumentation anscheinend nicht anders aussagt), liegt dies höchstwahrscheinlich daran, dass sie nicht in regulären Bezeichnern verwendet werden können in integrierten Funktionen vor der Einführung von Supplementary Character-Aware Collations wurden in SQL Server 2012 eingeführt (sie werden als zwei einzelne "unbekannte" Zeichen behandelt). In nicht-binären Collations vor der Einführung von 100 konnten sie nicht einmal voneinander unterschieden werden. Sortierfolgen (eingeführt in SQL Server 2008).
In Bezug auf ASCII: 8-Bit-Codierungen werden hier nicht verwendet, da alle Bezeichner Unicode / NVARCHAR
/ UTF-16 LE sind. Die Anweisung SELECT ASCII('ツ');
gibt einen Wert zurück, der 63
ein "?" (try:) SELECT CHAR(63);
da dieses Zeichen, auch wenn es mit einem Großbuchstaben "N" versehen ist, sicher nicht in Codepage 1252 enthalten ist. Dieses Zeichen befindet sich jedoch in der koreanischen Codepage und liefert das richtige Ergebnis, auch ohne das "N" "Präfix in einer Datenbank mit einer koreanischen Standardsortierung:
SELECT UNICODE('ツ'); -- 12484
In Bezug auf den ersten Buchstaben, der das Ergebnis beeinflusst: Dies ist nicht möglich, da der erste Buchstabe für lokale Variablen und Parameter immer ist @
. Der erste Buchstabe, den wir für diese Namen steuern können, ist das zweite Zeichen des Namens.
Bezüglich der Frage, warum lokale Variablennamen, Parameternamen und GOTO
Bezeichnungen nicht abgegrenzt werden können: Ich vermute, dass dies daran liegt, dass diese Elemente Teil der Sprache selbst sind und nicht als Daten in eine Systemtabelle gelangen.
Ich glaube nicht, dass Unicode das Problem verursacht. Bei lokalen Variablen- oder Parameternamen ist das Zeichen kein gültiges ASCII / Unicode 3.2-Zeichen (und es gibt keine Escape-Sequenz für Variablen / Parameter wie für andere Entitätstypen).
Dieser Batch funktioniert einwandfrei. Er verwendet ein Unicode-Zeichen, das die Regeln für nicht begrenzte Bezeichner einfach nicht verletzt:
Sobald Sie versuchen, einen Schrägstrich oder Bindestrich zu verwenden, bei denen es sich um gültige ASCII-Zeichen handelt, wird Folgendes bombardiert:
In der Dokumentation wird nicht erläutert, warum diese Bezeichner geringfügig anderen Regeln unterliegen als alle anderen Bezeichner oder warum sie nicht wie die anderen maskiert werden können.
quelle
@
Um hier einige Punkte zu verdeutlichen: 1) Das erste Zeichen ist kein Problem, da das erste Zeichen der Name var / param ist. Alle Zeichen, die nicht funktionieren, sollten an keiner Position funktionieren, auch wenn ihnen gültige Zeichen vorangestellt sind. 2) Das Dokument gibt nur an, dass Zusatzzeichen nicht in regulären Bezeichnern verwendet werden können (was für alle von mir ausgeführten Versuche der Fall zu sein scheint), sondern begrenzt begrenzte Bezeichner nicht, genau wie bei eingebetteten Leerzeichen. Ich glaube auch, dass dies anders ist, weil sie Teil der T-SQL-Sprache sind und nicht der Datenbank.GOTO
die einzige Einschränkung die Länge ist , wenn Variablen- / Parameternamen und Bezeichnungen getrennt werden dürfen. Ich kann nur davon ausgehen, dass das Parsen und / oder Behandeln dieser wenigen Elemente auf einer anderen Ebene erfolgt oder dass andere Einschränkungen dafür verantwortlich sind, dass begrenzte Werte nicht mehr ausgeführt werden können. Zumindest hoffe ich, dass es nicht willkürlich oder ein Versehen war.is_alphabetic
oder markiert wurdennumeric_type=decimal
.