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. 1台のマシンと1つのプラットフォームで比較が同じように動作しないのに、環境が異なる理由
  3. これらの4つのキャラクターは人間が理解できる1つのキャラクターを表しています。なぜUnicode文字マップが非常に豊富なのですか?

もちろん、これは非常に大きな問題になります。私はテキスト処理アプリケーションに取り組んでおり、データはほぼどこからでも来ており、処理する前にテキストを正規化する必要があるためです。

違いの理由がわかっていれば、それを処理する解決策を見つけるかもしれません。ありがとうございました。

回答:


28

SQL Serverのすべての文字データは照合に関連付けられます。照合は、保存できる文字のドメインと、データの比較と並べ替えに使用されるルールを決定します。照合は、Unicodeデータと非Unicodeデータの両方に適用されます。

SQL Serverには、バイナリ、レガシ、およびWindowsの3つの広範なカテゴリの照合が含まれます。バイナリカテゴリ(_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;

ユニコードに同一のグリフの異なるコードポイントが含まれる理由については、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.