1つの「キャラクター」(複数のコードポイントで構成されることがあります:サロゲートペア、キャラクターの組み合わせなど)が他の「キャラクター」と比較される方法は、かなり複雑なルールセットに基づいています。Unicode仕様で表されているすべての言語に見られるさまざまな(そして時々「奇抜な」)ルールすべてを考慮する必要があるため、非常に複雑です。このシステムは、すべてのNVARCHAR
データ、およびVARCHAR
SQL Server照合ではなくWindows照合を使用しているデータ(1で始まるものSQL_
)の非バイナリ照合に適用されます。このシステムはVARCHAR
、単純なマッピングを使用するため、SQL Server Collationを使用するデータには適用されません。
ほとんどのルールは、Unicode Collation Algorithm(UCA)で定義されています。これらのルールの一部と、UCAでカバーされていないルールは次のとおりです。
allkeys.txt
ファイルで指定されているデフォルトの順序/重み(以下に記載)
- どの感度とオプションが使用されているか(たとえば、大文字と小文字を区別するのか、区別しないのか、大文字と小文字を区別する場合は、大文字が最初か小文字が最初か)
- ロケールベースのオーバーライド。
- Unicode標準のバージョンが使用されています。
- 「人間」要素(つまり、Unicodeはソフトウェアではなく仕様であるため、各ベンダーが実装する必要があります)
ヒューマンファクターに関する最後のポイントは、SQL Serverが仕様に従って常に100%動作することを期待してはならないことを明確にすることです。
ここでの最大の要因は、各コードポイントに与えられる重みと、複数のコードポイントが同じ重み仕様を共有できるという事実です。基本的な重み(ロケール固有のオーバーライドはありません)は、ここで見つけることができます(100
一連の照合順序はUnicode v 5.0であると信じています-Microsoft Connectアイテムのコメントでの非公式の確認)。
http://www.unicode.org/Public/UCA/5.0.0/allkeys.txt
問題のコードポイント– U + FFFD –は次のように定義されます。
FFFD ; [*0F12.0020.0002.FFFD] # REPLACEMENT CHARACTER
その表記法は、セクション9.1 UCAのAllkeysファイル形式で定義されています。
<entry> := <charList> ';' <collElement>+ <eol>
<charList> := <char>+
<collElement> := "[" <alt> <weight> "." <weight> "." <weight> ("." <weight>)? "]"
<alt> := "*" | "."
Collation elements marked with a "*" are variable.
この最後の行は重要です。コードポイントには実際に「*」で始まる仕様があるためです。セクション3.6 Variable Weightingには、直接アクセスできない照合設定値に基づいて4つの可能な動作が定義されています(これらは、大文字と小文字を区別するかどうかなど、Microsoftの各照合の実装にハードコードされています最初に大文字、照合をVARCHAR
使用するデータSQL_
と他のすべてのバリエーションで異なるプロパティ)。
より確実な証明を提供できるように、どのパスが使用されるかを完全に調査し、どのオプションが使用されているかを推測する時間はありませんが、各コードポイント仕様内で、何かにかかわらず「等しい」と見なされると、常に完全な仕様が使用されるとは限りません。この場合、「0F12.0020.0002.FFFD」があり、ほとんどの場合、使用されているのはレベル2と3だけです(つまり.0020.0002。)。「.0020.0002」のメモ帳++で「カウント」を行う 12,581件の一致を検出します(まだ処理していない補助文字を含む)。「[*」で「Count」を実行すると、4049件の一致が返されます。次のパターンを使用して正規表現「検索」/「カウント」を行う\[\*\d{4}\.0020\.0002
832件の一致を返します。そのため、この組み合わせのどこかと、おそらく私が見ない他のいくつかのルールと、Microsoft固有の実装の詳細が、この動作の完全な説明です。明確にするために、ルールが適用されるとすべて同じ重みを持つため、一致するすべての文字の動作は同じです(つまり、この質問は、それらのいずれかについて尋ねられた可能性があります必ず氏�
)。
COLLATE
以下のクエリを使用して、2つのバージョンの照合でさまざまな感度がどのように機能するかをクエリの下の結果に従って句を変更することで確認できます。
;WITH cte AS
(
SELECT TOP (65536) ROW_NUMBER() OVER (ORDER BY (SELECT 0)) - 1 AS [Num]
FROM [master].sys.columns col
CROSS JOIN [master].sys.objects obj
)
SELECT cte.Num AS [Decimal],
CONVERT(VARBINARY(2), cte.Num) AS [Hex],
NCHAR(cte.Num) AS [Character]
FROM cte
WHERE NCHAR(cte.Num) = NCHAR(0xFFFD) COLLATE Latin1_General_100_CS_AS_WS --N'�'
ORDER BY cte.Num;
異なる照合で一致する文字のさまざまなカウントは以下のとおりです。
Latin1_General_100_CS_AS_WS = 5840
Latin1_General_100_CS_AS = 5841 (The "extra" character is U+3000)
Latin1_General_100_CI_AS = 5841
Latin1_General_100_CI_AI = 6311
Latin1_General_CS_AS_WS = 21,229
Latin1_General_CS_AS = 21,230
Latin1_General_CI_AS = 21,230
Latin1_General_CI_AI = 21,537
上記のすべての照合では、N'' = N'�'
trueと評価されます。
更新
私はもう少し研究をすることができましたが、ここに私が見つけたものがあります:
「おそらく」動作する方法
ICU Collation Demoを使用して、ロケールを "en-US-u-va-posix"に設定し、強度を "primary"に設定し、show "sort keys"をオンにし、次の4文字をコピーしました。上記のクエリの結果(Latin1_General_100_CI_AI
照合を使用):
�
Ԩ
ԩ
Ԫ
そしてそれは返します:
Ԫ
60 2E 02 .
Ԩ
60 7A .
ԩ
60 7A .
�
FF FD .
次に、http:FF FD
//unicode.org/cldr/utility/character.jsp?a = fffdで文字プロパティの「 」を確認し、レベル1のソートキー(つまり)が「uca」プロパティと一致することを確認します。-その「UCA」プロパティをクリックすると、検索ページに移動しますhttp://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3Auca%3DFFFD%3A%5D -わずか1試合を示します。また、allkeys.txtファイルでは、レベル1のソートの重みはとして表示され0F12
、それに一致するものは1つだけです。
GREEK CAPITAL LETTER OMICRON WITH VARIA:私たちは正しく行動を解釈していることを確認するために、私は別の文字を見Ὸ
にhttp://unicode.org/cldr/utility/character.jsp?a=1FF8(「UCA」を持っていますすなわち、レベル1のソート重み/照合要素)の5F30
。-その「5F30」をクリックすると、検索ページに移動しますhttp://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3Auca%3D5F30%3A%5D - 30試合の20を示します0〜65535の範囲(つまり、U + 0000-U + FFFF)にあります。探しallkeys.txtコードポイント用のファイル1FF8、我々はレベル1ソートの重みを参照してください12E0
。Notepad ++で「カウント」を行う12E0.
30個の一致を示します(Unicode v 5.0のファイルであり、サイトはUnicode v 9.0のデータを使用しているため保証されませんが、Unicode.orgの結果と一致します)。
SQL Serverでは、次のクエリは20個の一致を返します。10個の補助文字を削除するときのUnicode.org検索と同じです。
;WITH cte AS
(
SELECT TOP (65535) ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS [Num]
FROM [master].sys.columns col
CROSS JOIN [master].sys.objects obj
)
SELECT cte.Num AS [Decimal],
CONVERT(VARCHAR(50), CONVERT(VARBINARY(2), cte.Num), 2) AS [Hex],
NCHAR(cte.Num) AS [Character]
FROM cte
WHERE NCHAR(cte.Num) = NCHAR(0x1FF8) COLLATE Latin1_General_100_CI_AI
ORDER BY cte.Num;
そして、念のため、ICU Collation Demoページに戻り、「入力」ボックスの文字を、SQL Serverの20個の結果のリストから取得した次の3文字に置き換えます。
Ὂ
𝜪
Ὸ
実際、これらはすべて同じ5F 30
レベル1のソートウェイトを持っていることを示しています(キャラクタープロパティページの「uca」フィールドに一致)。
SO、それは確かに、この特定の文字をすべきかのように思われるんではない何かを一致させます。
実際の動作(少なくともMicrosoftランドでは)
SQL Server内とは異なり、.NETにはCompareInfo.GetSortKey Methodを介して文字列のソートキーを表示する手段があります。このメソッドを使用して、U + FFFD文字だけを渡すと、ソートキーが返されます0x0101010100
。次に、0〜65535の範囲のすべての文字を反復処理して、0x0101010100
4529個の一致の返される並べ替えキーがあった文字を確認します。これは、SQL Serverで返された5840(Latin1_General_100_CS_AS_WS
照合を使用する場合)と完全には一致しませんが、Unicode vを使用するWindows 10および.NET Frameworkバージョン4.6.1を実行しているため、(現時点では)取得できる最も近いものです6.3.0 CharUnicodeInfoクラスのチャートによる(「発言者」の「備考」セクション)。現時点では、SQLCLR関数を使用しているため、ターゲットフレームワークのバージョンを変更できません。機会があれば、コンソールアプリを作成し、Unicode v 5.0を使用する4.5のターゲットフレームワークバージョンを使用します。これは、100シリーズの照合に一致する必要があります。
このテストが示すのは、.NETとU + FFFDのSQL Serverでまったく同じ数の一致がなくても、これがSQL Server固有の動作ではなく、実装が意図的であるか監視されているかは明らかです。Microsoftによると、U + FFFD文字は、Unicode仕様に従っていなくても、実際にかなりの数の文字と一致します。そして、この文字がU + 0000(null)に一致することを考えると、おそらく重みの欠落の問題にすぎません。
また
=
クエリとクエリの動作の違いについてはLIKE N'%�%'
、ワイルドカードと、これらの(つまり� Ƕ Ƿ Ǹ
)文字の欠落している(と思われる)重みに関係しています。LIKE
条件が単純に変更されると、条件とLIKE N'�'
同じ3行が返され=
ます。ワイルドカードの問題が「欠落」ウェイトによるものではない場合(btw 0x00
によってソートキーが返されないCompareInfo.GetSortKey
場合)、コンテキストに基づいてソートキーを変更できるプロパティを持つ可能性があるこれらの文字(つまり、周囲の文字) )。
FFFD
(検索*0F12.0020.0002.FFFD
は1つの結果のみを返します)。@Forrestの観察では、これらはすべて空の文字列に一致し、件名についてもう少し読むと、さまざまな非バイナリ照合で共有する重みは実際にはゼロであるように見えます。