Bene, gli identificatori sono sempre Unicode / NVARCHAR
, quindi tecnicamente non puoi creare nulla che non abbia un nome Unicode 🙃.
Il problema che stai riscontrando qui è dovuto interamente alla classificazione del personaggio (i) in uso. Le regole per gli identificatori regolari (cioè non delimitati) sono:
- La prima lettera deve essere:
- Una lettera come definita dallo standard Unicode 3.2.
- trattino basso (_), al segno (@) o segno numerico (#)
- Le lettere successive possono essere:
- Lettere come definito nello standard Unicode 3.2.
- Numeri decimali dal latino di base o da altri script nazionali.
- trattino basso (_), al segno (@), segno numerico (#) o segno del dollaro ($)
- Non sono ammessi spazi incorporati o caratteri speciali.
- Non sono ammessi caratteri supplementari.
Ho messo in grassetto le uniche regole che contano in questo contesto. La ragione per cui le regole della "Prima lettera" non sono rilevanti qui è che la prima lettera in tutte le variabili e i parametri locali è sempre "al segno" @
.
E per essere chiari: ciò che è considerato una "lettera" e ciò che è considerato una "cifra decimale" si basa sulle proprietà assegnate a ciascun carattere nel database dei caratteri Unicode. Unicode assegna molte proprietà a ciascun carattere, come ad esempio: is_uppercase, is_lowercase, is_digit, is_decimal, is_combining, ecc. Ecc. Queste proprietà vengono spesso utilizzate nelle espressioni regolari per corrispondere alla "punteggiatura", ecc. Ad esempio, \p{Lu}
corrisponde a qualsiasi lettera maiuscola (in tutte le lingue / script) e \p{IsDingbats}
corrisponde a qualsiasi carattere "Simboli".
Quindi, nel tuo tentativo di fare:
DECLARE @¯\_(ツ)_/¯ INT;
solo i caratteri _
(trattino basso o "linea bassa") e ツ
(Katakana Letter Tu U + 30C4) rientrano in quelle regole. Ora, tutti i caratteri in ¯\_(ツ)_/¯
vanno bene per gli identificatori delimitati, ma sfortunatamente sembra che i nomi e le GOTO
etichette di variabili / parametri non possano essere delimitati (sebbene i nomi dei cursori possano esserlo).
Quindi, per i nomi di variabili / parametri, poiché non possono essere delimitati, si è bloccati nell'utilizzare solo caratteri che si qualificano come "lettere" o "cifre decimali" a partire da Unicode 3.2 (bene, secondo la documentazione; ho bisogno di testare se le classificazioni sono state aggiornate per le versioni più recenti di Unicode poiché le classificazioni sono gestite in modo diverso rispetto ai pesi di ordinamento).
TUTTAVIA # 1 , le cose non sono così semplici come dovrebbero essere. Sono stato ora in grado di completare la mia ricerca e ho scoperto che la definizione dichiarata non è del tutto corretta. La definizione precisa (e verificabile) di quali caratteri sono validi per identificatori regolari è:
Primo personaggio:
- Può essere qualsiasi cosa classificata in Unicode 3.2 come "ID_Start" (che include "Lettere" ma anche "caratteri numerici simili a lettere")
- Può essere
_
(linea bassa / trattino basso) o _
(linea bassa larghezza intera)
- Può essere
@
, ma solo per variabili / parametri
- Può essere
#
, ma se oggetto associato a schema, solo per tabelle e stored procedure (nel qual caso indicano che l'oggetto è temporaneo)
Personaggi successivi:
- Può essere qualsiasi cosa classificata in Unicode 3.2 come "ID_Continua" (che include numeri "decimali", ma anche "segni di combinazione spaziatura e non spaziatura" e "collegamento di segni di punteggiatura")
- Può essere
@
, #
o$
- Può essere uno qualsiasi dei 26 caratteri classificati in Unicode 3.2 come caratteri di controllo del formato
(fatto divertente: "ID" in "ID_Start" e "ID_Continue" sta per "Identificatore". Immagina che ;-)
Secondo "Unicode Utilities: UnicodeSet":
Caratteri iniziali validi
[: Età = 3.2:] & [: ID_Start = Sì:]
-- 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'.
*/
Caratteri di continuazione validi
[: Età = 3.2:] & [: ID_Continue = Sì:]
-- 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
TUTTAVIA # 2 , nemmeno la ricerca nel database Unicode può essere così facile. Queste due ricerche producono un elenco di caratteri validi per tali categorizzazioni e quei caratteri provengono da Unicode 3.2, MA le definizioni delle varie modifiche alle categorizzazioni attraverso le versioni dello standard Unicode. Significato, la definizione di "ID_Start" in Unicode v 10.0 (ciò che quella ricerca sta usando oggi, 26-03-2018) non è quella che era in Unicode v 3.2. Pertanto, la ricerca online non può fornire un elenco esatto. Ma puoi prendere i file di dati Unicode 3.2 e prendere la lista dei caratteri "ID_Start" e "ID_Continue" da lì per confrontare con ciò che SQL Server effettivamente utilizza. E ho fatto questo e confermato una corrispondenza esatta con le regole che ho affermato sopra in "TUTTAVIA # 1".
I seguenti due post del blog descrivono in dettaglio i passaggi da seguire per trovare l'elenco esatto dei caratteri, inclusi i collegamenti agli script di importazione:
- Il codice Uni: la ricerca del vero elenco di caratteri validi per identificatori regolari T-SQL, parte 1
- Il codice Uni: la ricerca del vero elenco di caratteri validi per identificatori regolari T-SQL, parte 2
Infine, per chiunque voglia solo vedere l'elenco e non si preoccupa di ciò che è stato necessario per scoprirlo e verificarlo, lo puoi trovare qui:
Elenco completamente completo di caratteri identificativi T-SQL validi
(si prega di dare alla pagina un momento per caricare; sono 3,5 MB e quasi 47k righe)
Per quanto riguarda i caratteri ASCII "validi", come /
e -
, non funzionanti: il problema non ha nulla a che vedere con la definizione o meno dei caratteri nel set di caratteri ASCII. Per essere valido, il personaggio deve avere la proprietà ID_Start
o ID_Continue
oppure deve essere uno dei pochi caratteri personalizzati annotati separatamente. Esistono alcuni caratteri ASCII "validi" (62 dei 128 totali - principalmente caratteri di punteggiatura e di controllo) che non sono validi negli identificatori "regolari".
Per quanto riguarda i caratteri supplementari: sebbene possano certamente essere utilizzati in identificatori delimitati (e la documentazione non sembra indicare diversamente), se è vero che non possono essere utilizzati in identificatori regolari, è molto probabile che non siano pienamente supportati nelle funzioni incorporate prima delle regole di confronto con riconoscimento dei caratteri supplementari sono state introdotte in SQL Server 2012 (vengono trattate come due singoli caratteri "sconosciuti"), né potrebbero essere differenziate tra loro in regole di confronto non binarie prima del 100- Collazioni di livello (introdotte in SQL Server 2008).
Per quanto riguarda ASCII: le codifiche a 8 bit non vengono utilizzate qui poiché tutti gli identificatori sono Unicode / NVARCHAR
/ UTF-16 LE. L'istruzione SELECT ASCII('ツ');
restituisce un valore di 63
cui è un "?" (prova:) SELECT CHAR(63);
dal momento che quel carattere, anche se preceduto da una "N" maiuscola, non è certamente nel Codice Pagina 1252. Tuttavia, quel carattere è nel Codice pagina coreano e produce il risultato corretto, anche senza la "N" "prefisso, in un database con regole di confronto predefinite coreane:
SELECT UNICODE('ツ'); -- 12484
Per quanto riguarda la prima lettera che influisce sul risultato: ciò non è possibile poiché la prima lettera per variabili e parametri locali è sempre @
. La prima lettera che possiamo controllare per questi nomi è in realtà il 2 ° carattere del nome.
Per quanto riguarda il motivo per cui i nomi delle variabili locali, i nomi dei parametri e le GOTO
etichette non possono essere delimitati: sospetto che ciò sia dovuto al fatto che questi elementi fanno parte del linguaggio stesso e non qualcosa che troverà la sua strada in una tabella di sistema come dati.