เหตุใดอักขระเหล่านี้จึงเท่าเทียมกันใน SQL Server


20

ฉันแค่ไม่เข้าใจ ดูแบบสอบถาม SQL นี้:

select nchar(65217) -- ﻁ
select nchar(65218) -- ﻂ
select nchar(65219) -- ﻃ
select nchar(65220) -- ﻄ
if nchar(65217) = nchar(65218)
    print 'equal'
if nchar(65217) = nchar(65219)
    print 'equal'
if nchar(65217) = nchar(65220)
    print 'equal'

ขึ้นอยู่กับความสัมพันธ์สกรรมกริยามันหมายความว่า SQL Server ถือว่าพวกเขาทั้งหมดจะเป็นตัวละครเดียวกัน

อย่างไรก็ตามในสภาพแวดล้อมอื่นพูดเช่น C # พวกเขาไม่เหมือนกัน

สิ่งที่ฉันสับสนคือ:

  1. การเปรียบเทียบสตริงทำงานใน SQL Server อย่างไร
  2. เหตุใดการเปรียบเทียบจึงไม่ทำงานเหมือนกันในเครื่องเดียวและแพลตฟอร์มเดียว แต่มีสภาพแวดล้อมที่แตกต่างกัน
  3. เหล่านี้เป็นตัวแทนของ 4 ตัวอักษรหนึ่งตัวละครมนุษย์ที่เข้าใจ ทำไมถึงมีมากมายในแมปอักขระ Unicode

ของหลักสูตรนี้ส่งผลให้เกิดปัญหาอย่างมากเพราะฉันกำลังทำงานกับแอปพลิเคชันการประมวลผลข้อความและข้อมูลมาจากเกือบทุกที่และฉันจำเป็นต้องทำให้ข้อความเป็นปกติก่อนประมวลผล

ถ้าฉันรู้เหตุผลของความแตกต่างฉันอาจหาทางแก้ปัญหาได้ ขอขอบคุณ.

คำตอบ:


28

ข้อมูลอักขระทั้งหมดใน SQL Server เชื่อมโยงกับการเปรียบเทียบซึ่งกำหนดโดเมนของตัวละครที่สามารถจัดเก็บได้เช่นเดียวกับกฎที่ใช้ในการเปรียบเทียบและเรียงลำดับข้อมูล การจัดเรียงใช้กับทั้ง Unicode และ Non-Unicode data

SQL Server ประกอบด้วย collations 3 ประเภทกว้าง ๆ : ไบนารีมรดกและ Windows การเรียงในหมวดหมู่ไบนารี ( _BINส่วนต่อท้าย) ใช้จุดรหัสพื้นฐานเพื่อเปรียบเทียบดังนั้นการเปรียบเทียบความเท่ากันจะส่งกลับไม่เท่ากันถ้าจุดรหัสแตกต่างกันโดยไม่คำนึงถึงตัวละคร การเปรียบเทียบแบบดั้งเดิม (ส่วนSQL_นำหน้า) และ Windows ให้การจัดเรียงและการเปรียบเทียบความหมายสำหรับกฎพจนานุกรมที่เป็นธรรมชาติยิ่งขึ้น สิ่งนี้ช่วยให้การเปรียบเทียบเพื่อพิจารณาตัวพิมพ์เล็กและใหญ่, ความกว้างและคะนะ การจัดเรียง Windows ให้word-sortกฎที่มีประสิทธิภาพมากขึ้นซึ่งสอดคล้องกับ Windows OS อย่างใกล้ชิดในขณะที่การเปรียบเทียบแบบดั้งเดิมพิจารณาเพียงอักขระเดียว

ตัวอย่างด้านล่างแสดงให้เห็นถึงความแตกต่างระหว่าง Windows และการเปรียบเทียบไบนารีด้วยอักขระ Teth:

CREATE TABLE dbo.WindowsColationExample
    (
      Character1 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character2 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character3 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character4 nchar(1) COLLATE Arabic_100_CI_AS_SC
    );

CREATE TABLE dbo.BinaryColationExample
    (
      Character1 nchar(1) COLLATE Arabic_100_BIN
    , Character2 nchar(1) COLLATE Arabic_100_BIN
    , Character3 nchar(1) COLLATE Arabic_100_BIN
    , Character4 nchar(1) COLLATE Arabic_100_BIN
    );

INSERT  INTO dbo.BinaryColationExample
VALUES  ( NCHAR(65217), NCHAR(65218), NCHAR(65219), NCHAR(65220) );
INSERT  INTO dbo.WindowsColationExample
VALUES  ( NCHAR(65217), NCHAR(65218), NCHAR(65219), NCHAR(65220) );

--all characters compare not equal
SELECT *
FROM dbo.BinaryColationExample
WHERE
    character1 = character2
    OR character1 = character3
    OR character1 = character4
    OR character2 = character3
    OR character2 = character4
    OR character3 = character4;

--all characters compare equal
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character2;
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character3;
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character4;
SELECT *
FROM dbo.WindowsColationExample
WHERE character2 = character3;
SELECT *
FROM dbo.WindowsColationExample
WHERE character2 = character4;
SELECT *
FROM dbo.WindowsColationExample
WHERE character3 = character4;

เหตุผลที่ว่าทำไม Unicode อาจจะมีจุดที่แตกต่างกันสำหรับรหัสร่ายมนตร์เหมือนมีการระบุไว้ใน http://en.wikipedia.org/wiki/Duplicate_characters_in_Unicode ฉันสรุปว่ามันอาจจะเป็นเพราะความเข้ากันได้แบบดั้งเดิมหรือตัวละครนั้นไม่เทียบเท่ามาตรฐาน โปรดทราบว่ามีการใช้อักขระ Teth ในภาษาต่างๆ ( http://en.wikipedia.org/wiki/Teth )


15

สิ่งนี้เกี่ยวข้องกับCOLLATIONฐานข้อมูลของคุณ ( ข้อมูลเพิ่มเติมใน BOL )

ฉันไม่แน่ใจทั้งหมดเกี่ยวกับภาษาของตัวละครเฉพาะที่คุณมีปัญหา (ฉันเดาว่าชาวเปอร์เซียอ้างอิงจากกระทู้นี้ ) แต่ถ้าคุณระบุการเปรียบเทียบที่ถูกต้องในตัวดำเนินการความเท่าเทียมคุณจะได้ผลลัพธ์ที่ถูกต้อง

if nchar(65217) COLLATE Persian_100_BIN = nchar(65218) COLLATE Persian_100_BIN 
    print 'equal'; -- nothing returned
if nchar(65217)  COLLATE Persian_100_BIN  = nchar(65217)  COLLATE Persian_100_BIN 
    print 'equal'; -- prints 'equal'
if nchar(65217) COLLATE Latin1_General_CI_AI = nchar(65220) COLLATE Latin1_General_CI_AI
    print 'equal'; -- prints 'equal'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.