Ya, pengidentifikasi selalu Unicode / NVARCHAR
, jadi secara teknis Anda tidak dapat membuat apa pun yang tidak memiliki nama Unicode 🙃.
Masalah yang Anda alami di sini sepenuhnya disebabkan oleh klasifikasi karakter yang digunakan. Aturan untuk pengidentifikasi reguler (yaitu tidak dibatasi) adalah:
- Huruf pertama harus:
- Surat seperti yang didefinisikan oleh Unicode Standard 3.2.
- garis bawah (_), pada tanda (@), atau tanda nomor (#)
- Surat-surat selanjutnya dapat:
- Surat-surat sebagaimana didefinisikan dalam Unicode Standard 3.2.
- Angka desimal dari bahasa Latin Dasar atau skrip nasional lainnya.
- garis bawah (_), pada tanda (@), tanda nomor (#), atau tanda dolar ($)
- Spasi tertanam atau karakter khusus tidak diperbolehkan.
- Karakter tambahan tidak diperbolehkan.
Saya berani satu-satunya aturan yang penting dalam konteks ini. Alasan bahwa aturan "Huruf pertama" tidak relevan di sini adalah bahwa huruf pertama di semua variabel dan parameter lokal selalu "di tanda" @
.
Dan untuk menjadi jelas: apa yang dianggap sebagai "huruf" dan apa yang dianggap sebagai "angka desimal" didasarkan pada properti yang masing-masing karakter ditugaskan di Database Karakter Unicode. Unicode memberikan banyak properti untuk setiap karakter, seperti: is_uppercase, is_lowercase, is_digit, is_decimal, is_combining, dll, dll. Ini bukan masalah apa yang kita fana akan pertimbangkan sebagai huruf atau angka desimal, tetapi karakter mana yang telah menetapkan properti ini. Properti ini sering digunakan dalam Ekspresi Reguler untuk mencocokkan pada "tanda baca", dll. Misalnya, \p{Lu}
cocok dengan huruf besar apa pun (di semua bahasa / skrip), dan \p{IsDingbats}
cocok dengan karakter "Dingbats" apa pun.
Jadi, dalam upaya Anda untuk melakukan:
DECLARE @¯\_(ツ)_/¯ INT;
hanya karakter _
(garis bawah atau "garis rendah") dan ツ
(Katakana Letter Tu U + 30C4) yang sesuai dengan aturan tersebut. Sekarang, semua karakter di dalam ¯\_(ツ)_/¯
adalah baik untuk pengidentifikasi dibatasi, tetapi sayangnya tampaknya variabel / nama parameter dan GOTO
label tidak dapat dibatasi (meskipun nama kursor dapat).
Jadi, untuk nama variabel / parameter, karena mereka tidak dapat dibatasi, Anda terjebak dengan hanya menggunakan karakter yang memenuhi syarat sebagai "huruf" atau "angka desimal" pada Unicode 3.2 (baik, menurut dokumentasi; saya perlu menguji jika klasifikasi telah diperbarui untuk versi Unicode yang lebih baru karena klasifikasi ditangani secara berbeda dari bobot sortir).
NAMUN # 1 , segala sesuatu tidak semudah yang seharusnya. Saya sekarang dapat menyelesaikan penelitian saya dan menemukan bahwa definisi yang dinyatakan tidak sepenuhnya benar. Definisi tepat (dan dapat diverifikasi) karakter mana yang valid untuk pengidentifikasi reguler adalah:
Karakter pertama:
- Dapat berupa apa saja yang diklasifikasikan dalam Unicode 3.2 sebagai "ID_Start" (yang meliputi "Surat" tetapi juga "karakter angka seperti huruf")
- Bisa
_
(garis rendah / garis bawah) atau _
(garis rendah bandwidth penuh)
- Bisa jadi
@
, tetapi hanya untuk variabel / parameter
- Dapat
#
, tetapi jika objek terikat skema, maka hanya untuk Tabel dan Prosedur yang Disimpan (dalam hal ini mereka menunjukkan bahwa objek bersifat sementara)
Karakter selanjutnya:
- Dapat berupa apa saja yang diklasifikasikan dalam Unicode 3.2 sebagai "ID_Continue" (yang termasuk angka "desimal", tetapi juga "spasi dan nonspacing menggabungkan tanda", dan "menghubungkan tanda baca")
- Bisa
@
, #
, atau$
- Dapat berupa 26 karakter yang diklasifikasikan dalam Unicode 3.2 sebagai karakter kontrol format
(Fakta menyenangkan: "ID" di "ID_Start" dan "ID_Continue" adalah singkatan dari "Identifier". Bayangkan ;-)
Menurut "Unicode Utilities: UnicodeSet":
Karakter awal yang valid
[: Usia = 3,2:] & [: ID_Start = Ya:]
-- 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'.
*/
Karakter kelanjutan yang valid
[: Usia = 3,2:] & [: ID_Continue = Ya:]
-- 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
NAMUN # 2 , bahkan tidak mencari database Unicode bisa semudah itu. Kedua pencarian tersebut menghasilkan daftar karakter yang valid untuk kategorisasi tersebut, dan karakter tersebut berasal dari Unicode 3.2, TETAPI definisi dari berbagai perubahan kategorisasi di seluruh versi Standar Unicode. Artinya, definisi "ID_Start" di Unicode v 10.0 (apa yang digunakan pencarian hari ini, 2018-03-26) tidak seperti di Unicode v 3.2. Jadi, pencarian online tidak dapat memberikan daftar yang tepat. Tetapi Anda dapat mengambil file data Unicode 3.2 dan mengambil daftar karakter "ID_Start" dan "ID_Continue" dari sana untuk membandingkan dengan apa yang sebenarnya digunakan oleh SQL Server. Dan saya telah melakukan ini dan mengonfirmasi kecocokan persis dengan aturan yang saya nyatakan di atas dalam "NAMUN # 1".
Dua posting blog berikut merinci langkah-langkah yang diambil untuk menemukan daftar karakter yang tepat, termasuk tautan ke skrip impor:
- The Uni-Code: Pencarian untuk Daftar True Karakter Valid untuk Pengidentifikasi Reguler T-SQL, Bagian 1
- The Uni-Code: Pencarian untuk Daftar True Karakter Valid untuk Pengidentifikasi Reguler T-SQL, Bagian 2
Akhirnya, bagi siapa saja yang hanya ingin melihat daftar dan tidak peduli dengan apa yang diperlukan untuk menemukan dan memverifikasinya, Anda dapat menemukannya di sini:
Daftar Lengkap Lengkap dari Karakter T-SQL Identifier yang Valid
(tolong beri halaman waktu untuk memuat; itu 3,5 MB dan hampir 47k baris)
Mengenai karakter ASCII "valid", seperti /
dan -
, tidak berfungsi: masalah tidak ada hubungannya dengan apakah karakter tersebut juga ditentukan dalam karakter ASCII atau tidak. Agar valid, karakter harus memiliki baik ID_Start
atau ID_Continue
properti, atau menjadi salah satu dari beberapa karakter kustom mencatat secara terpisah. Ada beberapa karakter ASCII "valid" (62 dari 128 total - sebagian besar tanda baca dan karakter kontrol) yang tidak valid dalam Identifikasi "Biasa".
Mengenai Karakter Tambahan: walaupun mereka tentu saja dapat digunakan dalam pengidentifikasi terbatas (dan dokumentasi tampaknya tidak menyatakan sebaliknya), jika memang benar mereka tidak dapat digunakan dalam pengidentifikasi reguler, kemungkinan besar karena mereka tidak didukung sepenuhnya dalam fungsi bawaan sebelum Pelengkap Sadar Karakter-Sadar diperkenalkan dalam SQL Server 2012 (mereka diperlakukan sebagai dua karakter "tidak dikenal" individu), mereka bahkan tidak dapat dibedakan satu sama lain dalam Koleksi non-biner sebelum 100- level Collations (diperkenalkan pada SQL Server 2008).
Mengenai ASCII: penyandian 8-bit tidak digunakan di sini karena semua pengidentifikasi adalah Unicode / NVARCHAR
/ UTF-16 LE. Pernyataan SELECT ASCII('ツ');
mengembalikan nilai 63
yang merupakan "?" (coba:) SELECT CHAR(63);
karena karakter itu, bahkan jika diawali dengan huruf besar "N", tentu saja tidak ada dalam Kode Page 1252. Namun, karakter itu ada di Halaman Kode Korea dan menghasilkan hasil yang benar, bahkan tanpa "N "awalan, dalam Database dengan Collation default Korea:
SELECT UNICODE('ツ'); -- 12484
Mengenai huruf pertama yang mempengaruhi hasil: ini tidak mungkin karena huruf pertama untuk variabel dan parameter lokal selalu @
. Huruf pertama yang bisa kita kontrol untuk nama-nama ini sebenarnya adalah karakter ke-2 dari nama tersebut.
Mengenai mengapa nama variabel lokal, nama parameter, dan GOTO
label tidak dapat dibatasi: Saya menduga ini karena item-item ini menjadi bagian dari bahasa itu sendiri dan bukan sesuatu yang akan menemukan jalannya ke tabel sistem sebagai data.
Saya tidak berpikir itu adalah Unicode yang menyebabkan masalah; dalam kasus variabel lokal atau nama parameter, karakternya bukan ASCII / Unicode 3.2 karakter yang valid (dan tidak ada urutan melarikan diri untuk variabel / parameter seperti ada untuk jenis entitas lainnya).
Batch ini berfungsi dengan baik, ia menggunakan karakter Unicode yang sama sekali tidak melanggar aturan untuk pengidentifikasi yang tidak dibatasi:
Segera setelah Anda mencoba menggunakan garis miring atau garis putus-putus, keduanya karakter ASCII yang valid, itu mengebom:
Dokumentasi tidak membahas mengapa ini pengidentifikasi tunduk pada aturan yang sedikit berbeda dari semua pengenal lainnya, atau mengapa mereka tidak dapat melarikan diri seperti yang lain.
sumber
@
dari nama var / param. Karakter apa pun yang tidak berfungsi seharusnya tidak berfungsi di posisi apa pun, meskipun didahului oleh karakter yang valid. 2) dokumen hanya menyatakan bahwa karakter tambahan tidak dapat digunakan dalam pengidentifikasi reguler (yang tampaknya merupakan kasus untuk semua yang telah saya coba), tetapi tidak menempatkan batasan pada pengidentifikasi terbatas, seperti halnya dengan ruang yang disematkan. Juga, saya percaya ini berbeda karena mereka adalah bagian dari bahasa T-SQL, bukan hal-hal di DB.GOTO
label variabel / parameter dibolehkan untuk dibatasi, maka satu-satunya batasan adalah panjangnya. Saya hanya dapat berasumsi bahwa penguraian dan / atau penanganan beberapa item tersebut terjadi pada level yang berbeda atau memiliki beberapa kendala lain yang membuat memungkinkan untuk nilai yang dibatasi tidak dapat bekerja. Setidaknya saya berharap itu tidak sewenang-wenang atau kelalaian.is_alphabetic
ataunumeric_type=decimal
.