Mengapa semua karakter ini sama di SQL Server?

20

Saya tidak mengerti. Lihat kueri SQL ini:

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'

Berdasarkan hubungan transitif , itu berarti bahwa SQL Server menganggap semuanya sebagai karakter yang sama.

Namun, di lingkungan lain, katakanlah misalnya C #, mereka tidak sama.

Yang saya bingung adalah:

  1. Cara perbandingan string bekerja di SQL Server
  2. Mengapa perbandingan tidak berlaku sama pada satu mesin, dan satu platform, tetapi lingkungan yang berbeda
  3. Keempat karakter ini mewakili satu karakter yang dapat dipahami manusia. Mengapa mereka begitu berlimpah di peta karakter Unicode?

Ini tentu saja menghasilkan masalah yang luar biasa, karena saya sedang mengerjakan aplikasi pemrosesan teks dan data datang hampir dari mana-mana dan saya perlu menormalkan teks sebelum memprosesnya.

Jika saya tahu alasan perbedaannya, saya mungkin menemukan solusi untuk menanganinya. Terima kasih.

Saeed Neamati
sumber

Jawaban:

28

Semua data karakter dalam SQL Server dikaitkan dengan pemeriksaan, yang menentukan domain karakter yang dapat disimpan serta aturan yang digunakan untuk membandingkan dan mengurutkan data. Collation berlaku untuk data Unicode dan Non-Unicode.

SQL Server mencakup 3 kategori besar kumpulan: biner, lawas, dan Windows. Koleksi dalam kategori biner ( _BINakhiran) menggunakan poin kode yang mendasarinya untuk membandingkan sehingga perbandingan kesetaraan mengembalikan tidak sama jika poin kode berbeda terlepas dari karakter. Koleksi lawas ( SQL_awalan) dan Windows menyediakan penyortiran dan perbandingan semantik untuk aturan kamus yang lebih alami. Ini memungkinkan perbandingan untuk mempertimbangkan case, aksen, lebar, dan Kana. Windows collations menyediakan word-sortaturan yang lebih kuat yang erat selaras dengan OS Windows sedangkan collacy legacy hanya mempertimbangkan karakter tunggal.

Contoh di bawah ini mengilustrasikan perbedaan antara Windows dan pengumpulan biner dengan karakter 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;

Alasan mengapa Unicode dapat berisi titik kode yang berbeda untuk mesin terbang yang identik diuraikan di http://en.wikipedia.org/wiki/Duplicate_characters_in_Unicode . Saya ringkas, itu mungkin untuk kompatibilitas warisan atau karakter tidak setara dengan kanonik. Perhatikan bahwa karakter Teth digunakan dalam berbagai bahasa ( http://en.wikipedia.org/wiki/Teth ).

Dan Guzman
sumber
15

Ini ada hubungannya dengan COLLATIONdatabase Anda ( informasi lebih lanjut dalam BOL ).

Saya tidak sepenuhnya yakin dengan bahasa karakter spesifik yang Anda hadapi (Saya menduga Persia berdasarkan utas ini ), tetapi jika Anda menentukan susunan yang benar di operator persamaan, maka Anda mendapatkan hasil yang akurat.

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'
Mark Sinkinson
sumber