web-dev-qa-db-ja.com

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

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'

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

19
cocogorilla

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

これは実際にはSQL Server固有の動作ではなく、これらが一般的に機能する方法です。

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

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

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

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

SQLサーバー

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

  1. まず、すべてのアクセントを削除し(「ü」が「u」になる)、「Æ」のような文字を展開します"を"[〜#〜] a [〜#〜]"および"[〜#〜] e [〜#〜]"にすると、次のようになります単語が自然な順序になるように最初に並べ替えます(辞書で単語をどのように見つけると期待できるか)。
  2. 次に、文字ごとに進み、各文字ごとにこれらの基になる値に基づいて同等性を決定します。この2番目の部分は、mustaccioが 彼の回答 で説明しているものです。

これらの照合で調整できる唯一の感度は、「ケース」と「アクセント」です(「幅」、「カナタイプ」、および「バリエーションセレクター」は使用できません)。また、これらの照合順序はいずれも補助文字をサポートしていません(これらは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モデルでは、ロケール、コードページ、およびさまざまな機密性の各組み合わせは、静的なマッピングが与えられている場合、notです。まず、このモデルにはコードページがありません。このモデルは、デフォルトのソート値を各文字に割り当て、各ロケール/カルチャーは、ソート値を任意の数の文字に再割り当てできます。これにより、複数のカルチャで同じ文字を異なる方法で使用できます。これは、複数の言語が同じ文字を使用しない場合(およびそれらの1つが値を再割り当てする必要がなく、デフォルトを使用できる場合)、同じ照合を使用して複数の言語を自然にソートできるようにする効果があります。

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

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

  1. 最初に、文字列は正規化されるため、同じ文字を表すさまざまな方法が同じになります。たとえば、「ü」は、単一の文字/コードポイント(U + 00FC)にすることができます。アクセントなしの「u」(U + 0075)と結合分音符号「̈」(U + 0308)を組み合わせて、次の情報を取得することもできます:「ü"、これはレンダリングされたときに同じように見えるだけでなく(フォントに問題がない限り)、単一文字バージョン(U + 00FC)と同じであるとも見なされます。バイナリ照合(文字ではなくバイトを比較する)を使用しない限り。正規化により、単一の文字がさまざまな部分に分割されます。これには、 ""などの文字の展開が含まれます(SQL Serverの照合順序で前述したとおり)。
  2. このモデルの比較演算は、文字ごとの各感度になります。文字列のソートキーは、各文字の適切な要素を適用することによって決定され、どの機密性が「機密」であるかに基づいて値の配列を照合します。並べ替えキーの値は、各文字(基本文字)のすべてのプライマリセンシティビティ、次にすべての2次感度(発音区別符号の重み)、各文字の大文字と小文字の重みなどの順に配置されます。
  3. ソートは、計算されたソートキーに基づいて実行されます。各機密性がグループ化されていると、複数の文字の文字列を比較するときに、同等のSQL Server照合順序とは異なる並べ替え順序が得られ、アクセントが含まれ、照合順序はアクセント記号に敏感です(さらに、照合順序が大文字と小文字も区別されます)。

この並べ替えの詳細については、最終的に、並べ替えキーの値、それらの計算方法、SQL ServerとWindowsの照合順序の違いなどを示す投稿を公開します。ただし、今のところ、私の回答をご覧ください アクセント記号順ソート (その質問に対する他の回答は公式のUnicodeアルゴリズムの適切な説明であることに注意してください。ただし、SQL Serverは代わりに、類似しているがカスタムのアルゴリズム、さらにはカスタムの重みテーブルを使用しています)。

これらの照合順序では、すべての機密性を調整できます。 "case"、 "accent"、 "width"、 "kana type"、および "variation selector"(SQL Server 2017以降、日本語の照合順序のみ)。また、これらの照合の一部(Unicodeデータで使用する場合)は、補足文字をサポートします(SQL Server 2012以降)。このアプローチは、両方のNVARCHARおよびVARCHARデータ(非Unicodeデータも含む)に適用されます。これは、非Unicodeに適用されますVARCHAR data最初に値をUnicodeに変換し、次に並べ替え/比較規則を適用します。


ご注意ください:

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

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

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

5
mustaccio