ตัวระบุเป็น Unicode เสมอ / NVARCHAR
ดังนั้นในทางเทคนิคคุณไม่สามารถสร้างสิ่งที่ไม่มีชื่อ Unicode ได้🙃
ปัญหาที่คุณมีที่นี่เกิดจากการจำแนกประเภทของตัวละครที่ใช้ กฎสำหรับตัวระบุปกติ (เช่นไม่มีการคั่น) คือ:
- ตัวอักษรตัวแรกจะต้อง:
- ตัวอักษรตามที่กำหนดโดย Unicode Standard 3.2
- เครื่องหมายขีดล่าง (_), ที่เครื่องหมาย (@) หรือเครื่องหมายหมายเลข (#)
- ตัวอักษรที่ตามมาสามารถเป็น:
- ตัวอักษรตามที่กำหนดใน Unicode Standard 3.2
- ตัวเลขทศนิยมจาก Basic Latin หรือสคริปต์ระดับชาติอื่น ๆ
- เครื่องหมายขีดล่าง (_), ที่เครื่องหมาย (@), เครื่องหมายหมายเลข (#), หรือเครื่องหมายดอลลาร์ ($)
- ไม่อนุญาตให้ใช้ช่องว่างหรืออักขระพิเศษ
- ไม่อนุญาตให้ใช้อักขระเพิ่มเติม
ฉันทำตัวหนาเฉพาะกฎที่สำคัญในบริบทนี้ เหตุผลที่ "ตัวอักษรตัวแรก" กฎที่ไม่เกี่ยวข้องที่นี่เป็นที่ตัวอักษรตัวแรกในทุกตัวแปรท้องถิ่นและพารามิเตอร์อยู่เสมอ @
"ที่เข้าสู่ระบบ"
และชัดเจน: สิ่งที่ถือว่าเป็น "ตัวอักษร" และสิ่งที่ถือว่าเป็น "เลขฐานสิบ" จะขึ้นอยู่กับคุณสมบัติที่ตัวละครแต่ละตัวได้รับมอบหมายในฐานข้อมูลอักขระ Unicode Unicode กำหนดคุณสมบัติมากมายให้กับแต่ละอักขระเช่น: is_uppercase, is_lowercase, is_digit, is_decimal, is_combining ฯลฯ ฯลฯ นี่ไม่ใช่เรื่องของสิ่งที่เราปุถุชนจะพิจารณาตัวอักษรหรือตัวเลขทศนิยม แต่ตัวละครที่ได้รับการกำหนดคุณสมบัติเหล่านี้ คุณสมบัติเหล่านี้มักจะใช้ในการแสดงออกปกติเพื่อให้ตรงกับ "เครื่องหมายวรรคตอน" ฯลฯ ตัวอย่างเช่น\p{Lu}
ตรงกับตัวอักษรตัวพิมพ์ใหญ่ (ในทุกภาษา / สคริปต์) และ\p{IsDingbats}
ตรงกับอักขระ "Dingbats" ใด ๆ
ดังนั้นในความพยายามของคุณที่จะทำ:
DECLARE @¯\_(ツ)_/¯ INT;
เฉพาะ_
อักขระ (ขีดล่างหรือ "เส้นต่ำ") และツ
(Katakana ตัวอักษร Tu U + 30C4) ที่พอดีกับกฎเหล่านั้น ตอนนี้อักขระทั้งหมดใน¯\_(ツ)_/¯
นั้นใช้ได้กับตัวระบุที่คั่นด้วย แต่น่าเสียดายที่ดูเหมือนว่าชื่อตัวแปร / พารามิเตอร์และGOTO
ป้ายกำกับไม่สามารถคั่นด้วย (แม้ว่าชื่อเคอร์เซอร์จะเป็น)
ดังนั้นสำหรับชื่อตัวแปร / พารามิเตอร์เนื่องจากไม่สามารถคั่นด้วยตัวคุณได้คุณใช้ตัวอักษรเท่านั้นที่มีคุณสมบัติว่าเป็น "ตัวอักษร" หรือ "ทศนิยม" ใน Unicode 3.2 (เช่นกันตามเอกสารประกอบ) ฉันต้องทดสอบ หากการจำแนกประเภทได้รับการอัปเดตสำหรับ Unicode รุ่นใหม่กว่าเนื่องจากการจำแนกประเภทได้รับการจัดการแตกต่างจากน้ำหนักการจัดเรียง)
อย่างไรก็ตาม # 1สิ่งต่าง ๆ ไม่ได้ตรงไปตรงมาเท่าที่ควร ตอนนี้ฉันสามารถทำวิจัยให้เสร็จและพบว่าคำจำกัดความที่ระบุนั้นไม่ถูกต้องทั้งหมด คำจำกัดความที่แม่นยำ (และตรวจสอบได้) ของอักขระที่ใช้ได้สำหรับตัวระบุปกติคือ:
ตัวละครแรก:
- สามารถจัดเป็นอะไรก็ได้ใน Unicode 3.2เป็น "ID_Start" (ซึ่งรวมถึง "ตัวอักษร" แต่ยัง "ตัวอักษรตัวเลขเหมือนตัวอักษร")
- สามารถ
_
(ต่ำ / ขีดเส้นใต้) หรือ_
(เต็มความกว้างของเส้นต่ำ)
- สามารถเป็น
@
แต่เพียงสำหรับตัวแปร / พารามิเตอร์
- สามารถ
#
แต่ถ้าวัตถุที่ถูกผูกสคีแล้วเท่านั้นสำหรับตารางและขั้นตอนการจัดเก็บ (ในกรณีที่พวกเขาระบุว่าวัตถุที่เป็นชั่วคราว)
อักขระที่ตามมา:
- สามารถเป็นอะไรก็ได้ที่จำแนกใน Unicode 3.2เป็น "ID_Continue" (ซึ่งรวมถึงตัวเลข "ทศนิยม" แต่ยังรวมถึง "การเว้นวรรคและไม่รวมเครื่องหมายการเว้นวรรค" และ "การเชื่อมต่อเครื่องหมายวรรคตอน")
- สามารถ
@
, #
หรือ$
- สามารถเป็นอักขระใด ๆ จาก 26 ตัวที่จัดอยู่ใน Unicode 3.2เป็นตัวควบคุมรูปแบบ
(ข้อเท็จจริงที่สนุกสนาน: "ID" ใน "ID_Start" และ "ID_Continue" หมายถึง "Identifier" ลองจินตนาการว่า ;-)
ตามที่ "Unicode Utilities: 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'.
*/
อักขระการต่อเนื่องที่ถูกต้อง
[: Age = 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 ก็สามารถทำได้อย่างง่ายดาย การค้นหาสองรายการเหล่านั้นสร้างรายการของอักขระที่ถูกต้องสำหรับ categorizations เหล่านั้นและอักขระเหล่านั้นมาจาก Unicode 3.2 แต่คำจำกัดความของ categorizations ต่างๆจะเปลี่ยนไปตามเวอร์ชันของ Unicode Standard ความหมายคำจำกัดความของ "ID_Start" ใน Unicode v 10.0 (การค้นหาที่ใช้อยู่ในปัจจุบันคือ 2018-03-26) ไม่ใช่สิ่งที่อยู่ใน Unicode v 3.2 ดังนั้นการค้นหาออนไลน์ไม่สามารถให้รายการที่แน่นอน แต่คุณสามารถคว้าไฟล์ข้อมูล Unicode 3.2 และคว้ารายการอักขระ "ID_Start" และ "ID_Continue" จากที่นั่นเพื่อเปรียบเทียบกับสิ่งที่ SQL Server ใช้จริง และฉันได้ทำสิ่งนี้แล้วและยืนยันการจับคู่ที่ตรงกันกับกฎที่ระบุไว้ข้างต้นใน "HOWEVER # 1"
โพสต์บล็อกสองรายการต่อไปนี้แสดงรายละเอียดขั้นตอนในการค้นหารายชื่อตัวละครที่แน่นอนรวมถึงลิงค์ไปยังสคริปต์นำเข้า:
- The Uni-Code: การค้นหารายชื่อตัวละครที่ถูกต้องสำหรับตัวระบุปกติของ T-SQL ตอนที่ 1
- The Uni-Code: การค้นหารายชื่อตัวละครที่ถูกต้องสำหรับตัวระบุปกติของ T-SQL ตอนที่ 2
ในที่สุดสำหรับใครก็ตามที่ต้องการดูรายการและไม่เกี่ยวข้องกับสิ่งที่จะค้นพบและตรวจสอบคุณสามารถค้นหาได้ที่นี่:
รายการที่สมบูรณ์แบบสมบูรณ์ของอักขระตัวระบุ T-SQL ที่ถูกต้อง
(โปรดให้เวลาในการโหลดหน้านี้เป็น 3.5 MB และเกือบ 47k บรรทัด)
เกี่ยวกับอักขระ ASCII "ที่ถูกต้อง" เช่น/
และ-
ไม่ทำงาน: ปัญหาไม่เกี่ยวข้องกับว่าอักขระนั้นถูกกำหนดในชุดอักขระ ASCII หรือไม่ เพื่อให้ถูกต้องตัวละครจะต้องมีอย่างใดอย่างหนึ่งID_Start
หรือID_Continue
ทรัพย์สินหรือเป็นหนึ่งในตัวละครที่กำหนดเองไม่กี่บันทึกแยกต่างหาก มีอักขระ ASCII "ที่ถูกต้อง" ไม่กี่ตัว (62 จาก 128 ตัว - ส่วนใหญ่เป็นเครื่องหมายวรรคตอนและอักขระควบคุม) ที่ไม่ถูกต้องในตัวระบุ "ปกติ"
เกี่ยวกับอักขระเสริม: ในขณะที่สามารถใช้ในตัวระบุที่คั่นได้ (และเอกสารไม่ได้ระบุว่าเป็นอย่างอื่น) หากเป็นจริงที่ไม่สามารถใช้ในตัวระบุปกติซึ่งน่าจะเป็นเพราะพวกเขาไม่ได้รับการสนับสนุนอย่างเต็มที่ ในฟังก์ชันที่มีอยู่แล้วภายในก่อนที่จะมีการแนะนำ Collationary Character-Aware Collation ใน SQL Server 2012 (พวกเขาจะถือว่าเป็นอักขระ "ไม่รู้จัก" สองตัว) และพวกเขาก็ไม่สามารถแยกความแตกต่างจากกันและกันในการเปรียบเทียบแบบไบนารีที่ไม่ใช่ 100 ระดับ Collations (แนะนำใน SQL Server 2008)
เกี่ยวกับ ASCII: การเข้ารหัส 8 บิตไม่ได้ถูกใช้ที่นี่เนื่องจากตัวระบุทั้งหมดเป็น Unicode / NVARCHAR
/ UTF-16 LE คำสั่งSELECT ASCII('ツ');
ส่งคืนค่า63
ซึ่งเป็น "?" (ลอง:) SELECT CHAR(63);
เนื่องจากตัวละครนั้นแม้ว่าจะนำหน้าด้วยตัวพิมพ์ใหญ่ "N" จะไม่ได้อยู่ใน Code Page 1252 อย่างไรก็ตามตัวละครนั้นอยู่ในหน้า Code ของเกาหลีและให้ผลลัพธ์ที่ถูกต้องแม้ไม่มี "N" "คำนำหน้าในฐานข้อมูลที่มีการเรียงหน้าเริ่มต้นภาษาเกาหลี:
SELECT UNICODE('ツ'); -- 12484
เกี่ยวกับตัวอักษรตัวแรกที่มีผลต่อผล: @
เป็นไปไม่ได้เนื่องจากตัวอักษรตัวแรกสำหรับตัวแปรท้องถิ่นและพารามิเตอร์อยู่เสมอ ตัวอักษรตัวแรกที่เราควบคุมชื่อเหล่านี้เป็นตัวอักษรตัวที่สองของชื่อ
เกี่ยวกับสาเหตุที่ชื่อตัวแปรโลคอลชื่อพารามิเตอร์และGOTO
เลเบลไม่สามารถถูกคั่น: ฉันสงสัยว่านี่เป็นเพราะรายการเหล่านี้เป็นส่วนหนึ่งของภาษาตัวเองและไม่ใช่สิ่งที่จะหาทางลงในตารางระบบเป็นข้อมูล