SQL Server'da neden bu karakterlerin hepsi eşittir?


20

Sadece anlamıyorum. Bu SQL sorgusuna bakın:

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'

Geçişli ilişkiye dayanarak, SQL Server'ın hepsinin aynı karakter olduğunu düşündüğü anlamına gelir.

Ancak, diğer ortamlarda, örneğin C # deyin, bunlar aynı değildir.

Hakkında kafam karıştı:

  1. SQL Server'da dize karşılaştırması nasıl çalışır?
  2. Karşılaştırma neden bir makinede ve bir platformda aynı şekilde davranmıyor, farklı ortamlarda çalışıyor
  3. Bu 4 karakter, insan tarafından anlaşılabilir bir karakteri temsil eder . Unicode karakter haritasında neden bu kadar bollar?

Bu, elbette çok büyük sorunlara yol açıyor, çünkü bir metin işleme uygulaması üzerinde çalışıyorum ve veriler neredeyse her yerden geliyor ve işlemeden önce metni normalleştirmem gerekiyor.

Eğer farkın nedenini bilirsem, bunun üstesinden gelmek için bir çözüm bulabilirim. Teşekkür ederim.

Yanıtlar:


28

SQL Server'daki tüm karakter verileri, depolanabilecek karakterlerin etki alanını ve verileri karşılaştırmak ve sıralamak için kullanılan kuralları belirleyen bir harmanlama ile ilişkilendirilir. Harmanlama hem Unicode hem de Unicode olmayan veriler için geçerlidir.

SQL Server 3 geniş harmanlama kategorisi içerir: ikili, eski ve Windows. İkili kategorideki ( _BINsonek) harmanlama, karşılaştırmak için temel alınan kod noktalarını kullanır, böylece kod noktaları karakterden bağımsız olarak değişirse eşitlik karşılaştırmaları eşit olmaz. Eski ( SQL_önek) ve Windows harmanlamaları, daha doğal sözlük kuralları için sıralama ve karşılaştırma semantiği sağlar. Bu, karşılaştırmaların büyük / küçük harf, aksan, genişlik ve Kana'yı dikkate almasını sağlar. Windows harmanlamaları word-sort, Windows işletim sistemiyle yakından uyumlu daha sağlam kurallar sağlarken, eski harmanlamalar yalnızca tek karakterleri dikkate alır.

Aşağıdaki örnek, Windows ve Teth karakteri ile ikili harmanlama arasındaki farkları göstermektedir:

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'un özdeş glifler için neden farklı kod noktaları içerebileceğinin nedenleri http://en.wikipedia.org/wiki/Duplicate_characters_in_Unicode içinde özetlenmiştir . Özetle, eski uyumluluk için olabilir veya karakterler kanonik olarak eşdeğer değildir. Teth karakterinin farklı dillerde kullanıldığını unutmayın ( http://en.wikipedia.org/wiki/Teth ).


15

Bunun COLLATIONveritabanınızla bir ilgisi vardır ( BOL'de daha fazla bilgi ).

Bir sorun yaşadığınız belirli karakterin dilinden tam olarak emin değilim ( bu konuya dayanarak Farsça tahmin ediyorum ), ancak eşitlik operatöründe doğru harmanlamayı belirtirseniz, doğru sonuçlar elde edersiniz.

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'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.