大文字と小文字を区別しない照合はどのように機能しますか?


19

SQL Serverの既定の照合タイプでは、大文字と小文字を区別しない文字列に対してインデックスを作成できますが、データの大文字と小文字は保持されます。これは実際にどのように機能しますか?実際のナットとボルト、ビットとバイト、または詳細を説明する優れたリソースを探しています。

create table casetest (fruitnames nvarchar(50) not null);
create unique index IX_fruitnames on casetest(fruitnames);

insert into casetest values ('apples');
insert into casetest values ('Pears');
-- this insert fails
insert into casetest values ('pears');

-- this yields 'Pears' as a result
select * from casetest (forceseek) where fruitnames = 'PEARS'

update casetest set fruitnames = 'pears' where fruitnames = 'pEArs'

-- this yields 'pears' as a result
select * from casetest (forceseek) where fruitnames = 'PEARS'

Robert SheldonのSQL Server照合に関する質問は、あまりにも恥ずかしがり屋でした。照合の使用方法について説明します。照合の仕組みについては説明しません。ケースデータを同時に保存しながら、ケースを気にせずにインデックスを効率的に作成/クエリする方法に興味があります。


1
大文字と小文字を区別するフィールドに対して、大文字と小文字を区別しない文字列を効率的にクエリ(たとえば、インデックスシークを使用)できますが、少し面倒です。
ジョンイスブレナー

cocogorilla:答えの最後に追加したメモ#1を参照してください:「デフォルト」照合。
ソロモンラッツキー

回答:


26

大文字と小文字を区別しない文字列に対してインデックスを作成しますが、データの大文字と小文字は保持されます。これは実際にどのように機能しますか?

これは実際にはSQL Server固有の動作ではなく、これらが一般的にどのように機能するかだけです。

したがって、データはデータです。インデックスについて具体的に説明している場合、データをそのまま保存する必要があります。それ以外の場合は、実際の値を取得するために毎回メインテーブルを検索する必要があり、カバーインデックスの可能性はありません(少なくとも文字列型ではありません)。

テーブル/クラスター化インデックスまたは非クラスター化インデックスのいずれかのデータには、照合/並べ替え情報含まれませ。それは単なるデータです。照合(ロケール/カルチャルールと感度)は、列に添付されたメタデータであり、並べ替え操作が呼び出されたときに使用されます(ただし、COLLATE句)、これにはインデックスの作成/再構築が含まれます。非バイナリ照合で定義されたルールは、文字列のバイナリ表現であるソートキーを生成するために使用されます(バイナリ照合ではソートキーは不要です)。これらのバイナリ表現には、すべてのロケール/カルチャルールと選択された感度が組み込まれています。ソートキーは、レコードを適切な順序で配置するために使用されますが、それ自体はインデックスまたはテーブルに保存されません。これらは保存されません(少なくとも、インデックスにこれらの値を見たことがなく、保存されていないと言われました)。

  1. とにかくテーブルまたはインデックスの行と同じ順序になるため、並べ替えには本当に必要ありません。ただし、インデックスの物理的な順序は並べ替えであり、比較ではありません。
  2. それらを保存すると比較が速くなるかもしれませんが、単一の文字の最小サイズが5バイトであるため、インデックスが大きくなり、それは(ソートキー構造の)「オーバーヘッド」にすぎません。ほとんどの文字はそれぞれ2バイトで、アクセントがある場合は1バイト、大文字の場合は1バイトです。たとえば、「e」は7バイトのキー、「E」と「é」は両方とも8バイト、「É」は9バイトのキーです。したがって、これらを最後に保存する価値はありません。

照合には、SQL ServerとWindowsの2種類があります。

SQLサーバー

SQL Serverの照合順序(名前がで始まるものSQL_)は、SQL Server 2000より前の古い並べ替え/比較の方法です(米国英語OSでのインストールのデフォルトのままですSQL_Latin1_General_CP1_CI_ASが、残念ながら)。この古い単純な非Unicodeモデルでは、ロケール、コードページ、およびさまざまな感度の各組み合わせに、そのコードページの各文字の静的マッピングが与えられます。各文字には、他の文字とどのように一致するかを示す値(ソートの重み)が割り当てられます。このモデルの比較は、2パス操作を実行するように見えます。

  1. まず、すべてのアクセントを削除し(「  ü  」が「u」になる   ように)、「Æ  」などの文字  を「  A  」と「  E  」に展開し、次に単語が自然な順序になるように初期ソートを実行します辞書でそれらを見つけることを期待してください)。
  2. 次に、文字ごとに移動して、各文字ごとにこれらの基礎となる値に基づいて同等性を判断します。この第2部はmustaccioが彼の答えで説明しいるものです。

これらの照合で調整できる感度は、「case」と「accent」のみです(「width」、「kana type」、および「variation selector」は使用できません)。また、これらの照合はいずれも補助文字をサポートしていません(これらはUnicode固有であり、これらの照合は非Unicodeデータにのみ適用されるため、意味があります)。

このアプローチは、非Unicode データにのみ適用されVARCHARます。ロケール、コードページ、大文字と小文字の区別、およびアクセントの区別の一意の組み合わせにはそれぞれ、特定の「ソートID」があります。これは次の例で確認できます。

SELECT COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CI_AS', 'SortID'), -- 52
       COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CS_AS', 'SortID'), -- 51
       COLLATIONPROPERTY(N'Latin1_General_100_CI_AS',     'SortID'); --  0

最初の2つの照合間の唯一の違いは、大文字と小文字の区別です。3番目の照合はWindows照合であるため、静的マッピングテーブルはありません。

また、これらの照合は、重みをソートするための文字の単純な検索であるため、Windows照合よりも速くソートおよび比較する必要があります。ただし、これらの照合は機能性がはるかに低いため、可能な限り回避する必要があります。

ウィンドウズ

Windows照合順序(名前を持つものではないから始まるがSQL_)を比較/ソートの新しい(SQL Server 2000で起動)方法です。この新しい複雑なUnicodeモデルでは、ロケール、コードページ、およびさまざまな感度の各組み合わせに静的マッピングが与えられていません。まず、このモデルにはコードページがありません。このモデルはデフォルトのソート値を各文字に割り当て、各ロケール/カルチャはソート値を任意の数の文字に再割り当てできます。これにより、複数のカルチャが異なる方法で同じキャラクターを使用できます。これは、同じ文字を使用しない場合(およびいずれかの値を再割り当てする必要がなく、単にデフォルトを使用できる場合)、同じ照合を使用して複数の言語を自然にソートできるようにする効果があります。

このモデルのソート値は単一の値ではありません。これらは、ベースレター、発音区別記号(アクセント)、大文字小文字などに相対的な重みを割り当てる値の配列です。照合で大文字と小文字が区別される場合、その配列の「大文字」部分が使用され、そうでない場合は無視されます(したがって、無反応)。照合がアクセントを区別する場合、配列の「発音区別符号」部分が使用されます。それ以外の場合は無視されます(したがって、区別されません)。

このモデルの比較はマルチパス操作です。

  1. 最初に、同じ文字を表すさまざまな方法が同等になるように、文字列が正規化されます。たとえば、「ü」は単一の文字/コードポイント(U + 00FC)です。また、アクセントのない「u」(U + 0075)と結合された分音記号「̈」(U + 0308)を組み合わせて、「ü」を取得することもできます。フォント)、バイナリ照合(文字の代わりにバイトを比較)を使用しない限り、単一文字バージョン(U + 00FC)と同じと見なされます。正規化は、単一の文字をさまざまな部分に分割します。これには、「Æ  」などの文字の拡張が含ま  れます(上記のSQL Server照合順序で説明したとおり)。
  2. このモデルの比較操作は、各感度ごとに文字ごとに行われます。文字列のソートキーは、各文字の適切な要素の値の照合配列を適用することで決定され、その感度に基づいて「感度」が決まります。ソートキーの値は、各文字の一次感度(基本文字)の順に並べられ、その後に二次感度(発音区別記号の重み)が続き、その後に各文字のケースの重みが続きます。
  3. ソートは、計算されたソートキーに基づいて実行されます。各機密性をグループ化すると、複数の文字の文字列を比較するときに同等のSQL Server照合順序とは異なる並べ替え順序を取得でき、アクセントが含まれます。照合順序はアクセントを区別します(照合順序が一致する場合はさらに大きくなります)大文字と小文字も区別されます)。

この並べ替えの詳細については、最終的に、並べ替えキーの値、計算方法、SQL ServerとWindowsの照合順序の違いなどを示す投稿を公開します。しかし、今のところ、アクセント付き並べ替え(その質問に対する他の答えは公式のUnicodeアルゴリズムの良い説明ですが、SQL Serverは代わりにカスタムのアルゴリズムを使用していますが、同様のアルゴリズム、さらにはカスタムの重みテーブルも使用しています)。

すべての感度は、「ケース」、「アクセント」、「幅」、「かなタイプ」、「バリエーションセレクター」の照合で調整できます(SQL Server 2017以降、日本語の照合のみ)。また、これらの照合の一部(Unicodeデータで使用する場合)は、補助文字(SQL Server 2012以降)をサポートしています。このアプローチはNVARCHAR VARCHARデータ非Unicodeデータの両方に適用されます。VARCHAR最初に値をUnicodeに内部的に変換し、次にソート/比較ルールを適用することにより、非Unicode データに適用されます。


ご注意ください:

  1. SQL Serverのユニバーサルデフォルト照合はありません。インストール時のOSの現在のロケール/言語設定に基づいて異なるインストールのデフォルトがあります(残念ながらSQL_Latin1_General_CP1_CI_AS米国英語のシステムの場合、この提案に投票しください)。これはインストール中に変更できます。このインスタンスレベルの照合[model]は、新しいDBの作成時に使用されるテンプレートであるDB の照合を設定しますが、実行時CREATE DATABASECOLLATE句を指定することで照合を変更できます。このデータベースレベルの照合順序は、変数および文字列リテラルに使用され、COLLATE句が指定されていない場合の新しい(および変更された!)列のデフォルトにも使用されます(質問のサンプルコードの場合)。
  2. 照合/エンコード/ Unicodeの詳細については、次をご覧ください。照合情報

5

通常、これは各キャラクターに特定のスコアを割り当てる照合テーブルを使用して実装されます。ソートルーチンには、デフォルトまたは明示的に指定された適切なテーブルを使用して、照合スコアを使用して文字列を文字ごとに比較するコンパレータがあります。たとえば、特定の照合テーブルが1のスコアを「a」に、201を「A」に割り当て、この特定の実装のスコアが低いほど優先順位が高いことを意味する場合、「a」は「A」の前に分類されます。別のテーブルでは、「a」に201、「A」に1の逆スコアを割り当てることができ、ソート順はその後逆になります。さらに別のテーブルでは、等しいスコアを「a」、「A」、「Á」、および「Å」に割り当て、大文字と小文字を区別せずに比較およびソートを行う場合があります。

同様に、インデックスキーと述語で指定された値を比較するときに使用される照合テーブルベースのコンパレータ。


1
参考までに:この情報はSQL_VARCHARデータで使用する場合、SQL Server照合(つまり、名前がで始まるもの)の使用に関してのみ正しいです。これがため、正確には当てはまりませんNVARCHARデータまたはVARCHARWindows照合順序を(名前は使用した場合のデータではないから始まりますSQL_)。
ソロモンラツキー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.