Wenn ich beispielsweise eine Ansicht mit einem Namen erstelle '4aii'
, warum kümmert es SQL Server dann, dass sie mit einem beginnt 4
? Ich könnte den Tisch anrufen Fouraii
oder IVaii
.
Was macht []
man außerdem hinter den Kulissen, damit eine Zeichenfolge als Name verwendet werden kann?
Eine Saite ist eine Saite, Amirite?
sql-server
identifier
James
quelle
quelle
Antworten:
Ja und Nein: Eine Zeichenfolge ist eine Zeichenfolge, aber Objekt- / Objektnamen sind keine Zeichenfolgen. Während diese Aussage wahr ist, ist sie auch nicht relevant für das Verhalten, das Sie sehen.
Ohne die konzeptionelle Begründung für die spezifischen Regeln zu beachten, lautet die technische Antwort auf "Warum eines funktioniert und nicht das andere", dass SQL Server (mit minimaler Anpassung) den Richtlinien des Unicode-Standards für Bezeichner folgt. Die Unicode-Dokumentation finden Sie hier:
Unicode®-Standardanhang Nr. 31: UNICODE IDENTIFIER UND MUSTERSYNTAX
Bezeichner, die weder enthalten
[...]
noch"..."
"reguläre" Bezeichner sind, während die eingeschlossenen Bezeichner "begrenzte" Bezeichner sind. Reguläre Bezeichner sind Namen, die in allen Kontexten gültig sind (dh dies sind die Regeln für die Benennung von Dingen in dieser Sprache, Software usw.). Begrenzte Bezeichner sind alles andere: Namen, die nicht gültig sind und nicht funktionieren sollten. Sie erhalten jedoch eine Ausnahme, wenn Sie sie in eines dieser Begrenzer einschließen. Die meisten Bezeichner können abgegrenzt werden. Es ist nurGOTO
Beschriftungen und Variablen (einschließlich Tabellenvariablen) / Parameter, die nicht begrenzt werden können. Der Unterschied scheint darin zu bestehen, dass Bezeichner, die nur zur Verwendung in der T-SQL-Sprache existieren (dh kein Name, der jemals in einer Datendatei oder Protokolldatei als Metadaten gespeichert wird), nicht abgegrenzt werden können (so wie Sie es erwarten würden) jede Sprache).Jetzt ist die SQL Server-Dokumentation nicht genau vollständig / korrekt, aber sie ist korrekt in Bezug auf die Klassifizierung eines gültigen "Bezeichners" (sowohl beginnend als auch fortlaufend) aus Unicode 3.2. Wenn Sie die tatsächliche Liste der Regeln für reguläre und begrenzte Bezeichner möchten, habe ich sie hier dokumentiert:
Vollständig vollständige Liste der Regeln für T-SQL-Kennungen
Besuchen Sie:
Behebung von Bedenken, die in Kommentaren zu dieser Antwort vermerkt sind:
_
,#
und@
wird in der Unicode - Spezifikation berücksichtigt. Abschnitt 1.2 Adressen Anpassungen an die Basisregeln und bietet sogar vier Beispiel Anpassungen:_
,#
,@
, und$
. Diese 4 vier "möglichen" Anpassungen sind genau die gleichen 4, die SQL Server verwendet. Daher lässt SQL Server dieses Unicode-Dokument als Quelle der Regeln zu@Variable
und#TempTable
verweist nicht darauf.Ident_Start
undIdent_Continue
in jeder neuen Version des Unicode-Standards werden Zeichen hinzugefügt . Der einzige Weg, um den richtigen Zeichensatz zu sehen, der diesen Eigenschaften entspricht, ist das Herunterladen von Unicode Version 3.2.AUCH in Bezug auf die im Titel angegebene Frage hängt es davon ab, wie locker Sie "Nummer" definieren. Das heißt, wenn Sie die in den beiden oben genannten Beiträgen gezeigten Forschungsschritte befolgen, sodass Sie eine Tabelle für die Unicode-Zeichendatenbank v3.2 und einige zusätzliche Eigenschaften erstellt haben, können Sie eine Liste mit 52 Nicht-Daten erhalten -Buchstaben (meistens "Zahlen"), die gültige Zeichen zum Starten eines Bezeichners über die folgende Abfrage sind:
Wenn wir einige dieser Charaktere zum Testen auswählen, können wir sehen, dass sie tatsächlich funktionieren:
Um zu zeigen, dass es sich bei ihnen nicht nur um Namen, sondern um "Zahlen" handelt, zeigt die folgende Abfrage, dass ihnen ein numerischer Wert zugewiesen wurde (wie in der
NumericValue
Spalte der[v3-2].UnicodeCharacterDatabase
Tabelle gezeigt):Es handelt sich jedoch nicht um Zahlen, die für numerische Operationen verwendet werden können:
In Bezug auf das Problem des Parsens und der Notwendigkeit, feststellen zu können, ob
3e2
es sich um eine Zahl oder einen Bezeichner handelt: Dies ist zwar eine Überlegung und möglicherweise der Grund, warum Zahlen aus der allgemeinen Unicode-Kategorie "Ident_start" ausgeschlossen sind, aber nicht universell und nicht unbedingt der Grund SQL Server schließt sie aus. Drei Punkte zu beachten:3e2
an sich nicht eindeutig ist, wäre es nicht: Wenn es mit mindestens einem Schemanamen qualifiziert wäre:dbo.3e2
4aii
ist überhaupt nicht mehrdeutig. Internes Parsen könnte dies leicht genug als keine potenzielle Zahl identifizierenMySQL / MariaDB Sie nicht haben diese Einschränkung. Sie ermöglichen nicht begrenzte Bezeichner wie
4aii
und3e
, aber nicht3e2
oder300
. In MySQL konnte ich Folgendes erfolgreich ausführen:Der Grund, warum Sie dies in SQL Server nicht tun können, liegt darin, dass SQL Server die Empfehlung des Unicode-Standards für Bezeichner einhält. Warum diese Charaktere vom Unicode-Konsortium ausgewählt wurden, ist nicht ausdrücklich angegeben, scheint aber zumindest "Best Practice" zu sein. Wie mit MySQL bewiesen, ist es dennoch möglich, Bezeichner zu analysieren, die mit einer Zahl beginnen.
quelle
A letter as defined by the Unicode Standard 3.2
, dass dies zwar nicht das gesamte Regelwerk ist, aber in diese Richtung weist. Und selbst wenn die ISO-Spezifikation diese genauen Regeln erwähnt, ist der Ursprung der Regeln immer noch das Unicode Identifier-Dokument.CREATE TABLE #foo ( a int )
, dass,#foo
ist eine Kennung , die Abgrenzung erfordern würde , wenn sie die Unicode - Spezifikation implementiert. Sie verwenden Unicode natürlich intern für ihren Lexer, aber ich habe keinen Grund zu der Annahme, dass ihr Ziel die Einhaltung von irgendetwas ist. Schauen Sie sich auchOther_ID_Start
keine dieser Arbeiten in Bezeichnern an.Zunächst müssen Sie zwischen Zahlen (numerische Literale), Zeichenfolgen (Zeichenfolgenliterale) und Bezeichnern unterscheiden.
'4aii'
ist ein String-Literal, das ein Wert für ein "Ding" sein kann, aber kein Ding identifiziert (benennt).4aii
oder[4aii]
wären Bezeichner (wenn es erlaubt wäre).Der Abfrageparser muss die Bedeutung eines Tokens verstehen, das er betrachtet. Indem Sie zulassen, dass Namen mit Ziffern beginnen, lassen Sie sie durch Erweiterung ausschließlich aus Ziffern bestehen. Dann gegeben
select 12345 from mytable
, wie würden Sie (und der Parser) wissen , ob12345
ein Ganzzahlliteral oder ein Name einer Spalte?Wenn Sie jedoch zulassen, dass Bezeichner nur mit Buchstaben (oder Unterstrichen) beginnen, können Sie eindeutig sagen, ob Sie einen Bezeichner (
abc123
) oder ein Zeichenfolgenliteral ('abc123'
) betrachten - letzteres ist in Anführungszeichen eingeschlossen.Eckige Klammern in SQL Server, Backticks (`) in MySQL und doppelte Anführungszeichen in ANSI SQL-kompatiblen Engines kennzeichnen Bezeichner, und Sie verwenden sie, wenn Ihre Bezeichner nicht ohne weiteres von anderen Token unterschieden werden können: Beginnen Sie mit einer Ziffer, haben Sie Leerzeichen oder andere Sonderzeichen in ihnen usw. Daher
[4aii]
oder"4aii"
sagen Sie dem Parser deutlich, dass es sich um eine Kennung handelt.Eine kleine Dbfiddle-Demo.
quelle
4aii
in MySQL ohne Begrenzer zu erstellen . Aber du kannst nicht3e2
oder300
.select [2]
"gib mir die zweite Spalte" bedeuten, was den armen ParserWas Sie beobachten, sind die Lexer-Regeln der Implementierung. Es ist Teil eines Prozesses, der als lexikalische Analyse bezeichnet wird und eine ausgefallene Art zu sagen ist, "Sinn für Dinge zu machen". Im Idealfall würde dies den in SQL Spec (
<identifier>
) angegebenen Regeln entsprechen . Diese Regeln werden alle von Microsoft als Regeln für reguläre Kennungen veröffentlicht . Wenn Sie unregelmäßige Bezeichner verwenden möchten, müssen Sie diese in Anführungszeichen setzen oder von anderen Token (Tsql[]
oder doppelte Anführungszeichen""
) "abgrenzen", wodurch alle Möglichkeiten einer mehrdeutigen Syntax ausgeschlossen werden.Nein, nehmen Sie zum Beispiel dies.
Das ist ein Satz. Aber was noch wichtiger ist, das sind 5 Wörter. Sie wissen, dass es fünf Wörter sind, weil das Leerzeichen von Bedeutung ist. Sie müssen wissen, dass es fünf Wörter sind, wenn Sie die Themen, Objekte und die Stimme analysieren möchten, um sie als Anweisung zu verstehen.
quelle
Ein kurzes Beispiel:
Ist das die Zeichenfolge "3e2"? Die Nummer 300? Ein Variablenname? Was ist, wenn Sie die Nummer gemeint haben und vergessen haben, dass Sie
3e2 = 500
früher in Ihrem Skript geschrieben haben?Die Regel ist vorhanden, damit ein Syntaxparser verstehen kann, was Sie meinen. Es kann nicht mehrdeutige Beispiele geben, wie
4aii
in Ihren Fragen erwähnt - aber es gibt eine Teilmenge von Labels, die mehrdeutig sind. Um diese Mehrdeutigkeit zu vermeiden, haben wir diese Regel.quelle
Ich hatte in den letzten 20 Jahren keine Probleme mit einer Ansicht namens
... aber dann hatte ich den Teufel einer Zeit, ein osql-Skript zu schreiben, um diese Ansicht (und andere, die sie mögen) vom Server (SQL Server 2000) zu löschen:
DROP VIEW würde nicht funktionieren, wenn diese Namen nicht zitiert würden.
Und es gab wie üblich einige arkane Einschränkungen bei der Verwendung der String-Verkettung sowie von EXEC und QUOTENAME.
Wenn Sie mit Ihren Werkzeugen keinen solchen Objektnamen erstellen können, seien Sie dankbar für kleine Gnaden.
quelle
@5
weil technisch gesehen das@
erste Zeichen ist, und temporäre Tabellen können sein,#5
weil das#
das erste Zeichen ist. Dies sollte also kein OSQL-Problem sein.