Perché questi caratteri sono tutti uguali in SQL Server?


20

Non capisco. Vedi questa query 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'

Basato su una relazione transitiva , significa che SQL Server li considera tutti dello stesso carattere.

Tuttavia, in altri ambienti, ad esempio C #, non sono gli stessi.

Ciò di cui sono confuso è:

  1. Come funziona il confronto delle stringhe in SQL Server
  2. Perché il confronto non si comporta allo stesso modo su una macchina e su una piattaforma, ma su ambienti diversi
  3. Questi 4 personaggi rappresentano un personaggio comprensibile all'uomo. Perché sono così abbondanti nella mappa dei caratteri Unicode?

Ciò ovviamente comporta enormi problemi, perché sto lavorando su un'applicazione di elaborazione testi e i dati provengono quasi da ogni parte e devo normalizzare il testo prima di elaborarlo.

Se conosco il motivo della differenza, potrei trovare una soluzione per gestirlo. Grazie.

Risposte:


28

Tutti i dati sui caratteri in SQL Server sono associati a regole di confronto, che determinano il dominio dei caratteri che è possibile archiviare nonché le regole utilizzate per confrontare e ordinare i dati. Le regole di confronto si applicano sia ai dati Unicode che Non Unicode.

SQL Server include 3 ampie categorie di regole di confronto: binario, legacy e Windows. Le regole di confronto nella categoria binaria ( _BINsuffisso) utilizzano i punti di codice sottostanti per confrontare, quindi i confronti di uguaglianza tornano non uguali se i punti di codice differiscono indipendentemente dal carattere. Le SQL_regole di confronto legacy ( prefisso) e Windows forniscono la semantica di ordinamento e confronto per le regole del dizionario più naturali. Ciò consente ai confronti di considerare caso, accenti, larghezza e Kana. Le regole di confronto di Windows forniscono regole più solide word-sortche si allineano strettamente al sistema operativo Windows, mentre le regole di confronto legacy considerano solo singoli caratteri.

L'esempio seguente illustra le differenze tra Windows e le regole di confronto binarie con il carattere 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;

I motivi per cui Unicode può contenere punti di codice diversi per gli stessi glifi sono indicati in http://en.wikipedia.org/wiki/Duplicate_characters_in_Unicode . Riassumo, potrebbe essere per compatibilità legacy o i personaggi non sono canonicamente equivalenti. Nota che il carattere Teth è usato in diverse lingue ( http://en.wikipedia.org/wiki/Teth ).


15

Ciò ha a che fare con il COLLATIONdatabase ( ulteriori informazioni in BOL ).

Non sono del tutto sicuro della lingua del personaggio specifico con cui stai riscontrando un problema (sto indovinando il persiano in base a questo thread), ma se specifichi la fascicolazione corretta nell'operatore di uguaglianza, otterrai risultati accurati.

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'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.