照合順序の優先順位 (Transact-SQL)

照合順序の優先順位は、照合順序強制適用ルールとも呼ばれ、次の照合順序を決定します。

  • 文字列として評価される式の最終的な結果の照合順序

  • LIKE、IN など、入力として文字列を使用するが文字列を返さない、照合順序依存の演算子によって使用される照合順序

照合順序の優先順位のルールは、char、varchar、text、nchar、nvarchar、および ntext の各文字列データ型に対してのみ適用されます。他のデータ型のオブジェクトは、照合順序の評価の対象にはなりません。

照合順序ラベル

すべてのオブジェクトの照合順序は 4 つのカテゴリに分類されます。これらのカテゴリの一覧とその説明を以下の表に示します。各カテゴリの名前を、照合順序ラベルと呼びます。

照合順序ラベル

オブジェクトの種類

強制可能な既定照合順序

任意の Transact-SQL 文字列変数、パラメータ、リテラル、カタログの組み込み関数の出力、または入力に文字列を使用しないが文字列を出力する組み込み関数の出力です。

このオブジェクトが、ユーザー定義関数、ストアド プロシージャ、またはトリガ内で宣言されている場合、そのオブジェクトには、関数、ストアド プロシージャ、またはトリガが作成されているデータベースの既定の照合順序が割り当てられます。オブジェクトがバッチ内で宣言されている場合は、その接続に対する現在のデータベースの既定の照合順序が割り当てられます。

暗黙的な照合順序 X

列参照です。式の照合順序 (X) には、テーブルまたはビューの列に対して定義されている照合順序が使用されます。

CREATE TABLE または CREATE VIEW ステートメントの COLLATE 句を使用して列に明示的に照合順序を割り当てても、その列参照は "暗黙" として分類されます。

明示的な照合順序 X

式の中で、COLLATE 句を使用して特定の照合順序 (X) に明示的にキャストされる式です。

照合順序なし

式の値が、2 つの文字列の照合順序ラベルが "暗黙" で、それぞれの照合順序が競合する場合のその文字列間の操作の結果であることを示します。式の結果は、照合順序なしとして定義されます。

照合順序ルール

文字列オブジェクトを 1 つだけ参照する単純な式の場合、その式の照合順序ラベルには、参照先のオブジェクトの照合順序ラベルが使用されます。

同じ照合順序ラベルを持つ 2 つのオペランド式を参照する複雑な式の場合、その式の照合順序ラベルには、オペランド式の照合順序ラベルが使用されます。

異なる照合順序を持つ 2 つのオペランド式を参照する複雑な式の場合、最終的な結果の照合順序ラベルは、次のルールに基づいて決定されます。

  • 明示的な照合順序は、暗黙的な照合順序よりも優先されます。暗黙的な照合順序は、強制可能な既定照合順序よりも優先されます。

    明示的な照合順序 > 暗黙的な照合順序 > 強制可能な既定照合順序

  • 異なる照合順序が割り当てられている 2 つの明示的な式を組み合わせると、エラーが発生します。

    明示的な照合順序 X + 明示的な照合順序 Y = エラー

  • 異なる照合順序を持つ 2 つの暗黙的な式を組み合わせると、照合順序なしになります。

    暗黙的な照合順序 X + 暗黙的な照合順序 Y = 照合順序なし

  • 照合順序なしの式と任意のラベルの式を組み合わせると、照合順序なしのラベルが生成されます。ただし、明示的な照合順序の場合は例外です。それについては次のルールを参照してください。

    照合順序なし + 任意 = 照合順序なし

  • 照合順序なしの式を、明示的な照合順序を持つ式と組み合わせると、明示的な照合順序のラベルを持つ式になります。

    照合順序なし + 明示的な照合順序 X = 明示的な照合順序

次の表は、ルールのまとめです。

オペランド強制ラベル

明示的な照合順序 X

暗黙的な照合順序 X

強制可能な既定照合順序

照合順序なし

明示的な照合順序 Y

エラーが生成されます。

結果は、明示的な照合順序 Y です。

結果は、明示的な照合順序 Y です。

結果は、明示的な照合順序 Y です。

暗黙的な照合順序 Y

結果は明示的な照合順序 X です。

結果は、照合順序なしです。

結果は、暗黙的な照合順序 Y です。

結果は、照合順序なしです。

強制可能な既定照合順序

結果は明示的な照合順序 X です。

結果は暗黙的な照合順序 X です。

結果は、強制可能な既定照合順序です。

結果は、照合順序なしです。

照合順序なし

結果は明示的な照合順序 X です。

結果は、照合順序なしです。

結果は、照合順序なしです。

結果は、照合順序なしです。

また、次の追加のルールも照合順序の優先順位に適用されます。

  • 式で明示的に照合順序が指定されている場合、その式にさらに COLLATE 句を指定することはできません。たとえば、次の WHERE 句は、既に明示的に照合順序が指定されている式に対して COLLATE 句が指定されているため、不正な式となります。

    WHERE ColumnA = ( 'abc' COLLATE French_CI_AS) COLLATE French_CS_AS

  • text 型で使用されるコード ページは変換できません。text 式の照合順序をキャストする場合、キャスト前とキャスト後の照合順序のコード ページが異なると、キャストできません。代入演算子を使用する場合、右側のテキスト オペランドの照合順序のコードページが左側のテキスト オペランドのコード ページと異なると、代入演算子は値を割り当てることができません。

照合順序の優先順位の決定は、データ型変換の後に行われます。結果の照合順序を提供するオペランドは、最終結果のデータ型を提供するオペランドと異なっていてもかまいません。たとえば、次のバッチがあるとします。

CREATE TABLE TestTab
   (PrimaryKey int PRIMARY KEY,
    CharCol char(10) COLLATE French_CI_AS
   )

SELECT *
FROM TestTab
WHERE CharCol LIKE N'abc'

N'abc' という単純な式の Unicode データ型は、データ型の優先順位が高いため、その結果式には N'abc' に割り当てられている Unicode データ型が使用されます。これに対し、式 CharCol は暗黙的な照合順序のラベルを持ち、N'abc' はそれよりも優先順位の低い強制可能な既定照合順序のラベルを持つため、照合順序には、CharCol の照合順序 French_CI_AS が使用されます。

照合順序ルールの例

照合順序ルールについて、以下の例で説明します。この例を実行するには、次に示すテスト テーブルを作成します。

USE tempdb;
GO

CREATE TABLE TestTab (
   id int, 
   GreekCol nvarchar(10) collate greek_ci_as, 
   LatinCol nvarchar(10) collate latin1_general_cs_as
   )
INSERT TestTab VALUES (1, N'A', N'a');
GO

照合順序の競合とエラー

次のクエリの述語に照合順序の競合が発生し、エラーが生成されます。

SELECT * 
FROM TestTab 
WHERE GreekCol = LatinCol;

以下に結果セットを示します。

Msg 448, Level 16, State 9, Line 2
Cannot resolve collation conflict between 'Latin1_General_CS_AS' and 'Greek_CI_AS' in equal to operation.

明示ラベルと暗黙ラベル

次のクエリの述語は、右側の式が明示ラベルを持っており、左側の式の暗黙ラベルよりも優先されるため、照合順序 greek_ci_as で評価されます。

SELECT * 
FROM TestTab 
WHERE GreekCol = LatinCol COLLATE greek_ci_as;

以下に結果セットを示します。

id          GreekCol             LatinCol
----------- -------------------- --------------------
          1 A                    a

(1 row affected)

照合順序なしのラベル

次のクエリの CASE 式の照合順序ラベルは、照合順序なしです。したがって、この式を選択リストに指定したり、照合順序依存の演算子によって処理することはできません。ただし、この式を、照合順序非依存の演算子を使用して処理することはできます。

SELECT (CASE WHEN id > 10 THEN GreekCol ELSE LatinCol END) 
FROM TestTab;

以下に結果セットを示します。

Msg 451, Level 16, State 1, Line 1
Cannot resolve collation conflict for column 1 in SELECT statement.

SELECT PATINDEX((CASE WHEN id > 10 THEN GreekCol ELSE LatinCol END), 'a')
FROM TestTab;

以下に結果セットを示します。

Msg 446, Level 16, State 9, Server LEIH2, Line 1
Cannot resolve collation conflict for patindex operation.

SELECT (CASE WHEN id > 10 THEN GreekCol ELSE LatinCol END) COLLATE Latin1_General_CI_AS 
FROM TestTab;

以下に結果セットを示します。

--------------------
a

(1 row affected)

照合順序依存と照合順序非依存

演算子と関数は、照合順序依存または非依存のいずれかです。

  • 照合順序依存
    照合順序依存とは、照合順序なしのオペランドを指定するとコンパイル時にエラーとなることを意味します。その式の結果を、照合順序なしに指定することはできません。

  • 照合順序非依存
    照合順序非依存とは、そのオペランドと結果を照合順序なしに指定できることを意味します。

演算子と照合順序

比較演算子、および MAX、MIN、BETWEEN、LIKE、IN の各演算子は、照合順序依存です。これらの演算子で使用される文字列には、優先順位の高い方のオペランドの照合順序ラベルが割り当てられます。また、UNION 演算子も照合順序依存で、すべての文字列オペランドおよび最終結果には、最高の優先順位を持つオペランドの照合順序が割り当てられます。UNION オペランドと結果の照合順序の優先順位は、列ごとに評価されます。

代入演算子は照合順序非依存で、右側の式が左側の照合順序にキャストされます。

文字列連結演算子は照合順序非依存で、2 つの文字列オペランドとその結果には、最高の優先順位を持つオペランドの照合順序ラベルが割り当てられます。UNION ALL および CASE 演算子は照合順序非依存で、すべての文字列オペランドとその最終結果には、最高の優先順位を持つオペランドの照合順序ラベルが割り当てられます。UNION ALL オペランドと結果の照合順序の優先順位は、列ごとに評価されます。

関数と照合順序

CAST、CONVERT、および COLLATE の各関数は、char 型、varchar 型、および text 型に関して照合順序依存です。CAST 関数および CONVERT 関数の入出力が文字列である場合、出力文字列は、入力文字列の照合順序ラベルを持ちます。入力が文字列ではない場合、出力文字列は強制可能な既定照合順序となり、その接続の現在のデータベースの照合順序、あるいは CAST または CONVERT を参照しているユーザー定義関数、ストアド プロシージャ、またはトリガを含むデータベースの照合順序が割り当てられます。

入力が文字列ではなく文字列を返す組み込み関数の場合、その結果文字列は強制可能な既定照合順序となり、現在のデータベースの照合順序、あるいはその関数を参照しているユーザー定義関数、ストアド プロシージャ、またはトリガを含むデータベースの照合順序が割り当てられます。

次の関数は、照合順序依存です。その出力文字列は、入力文字列の照合順序ラベルを持ちます。

CHARINDEX

REPLACE

DIFFERENCE

REVERSE

ISNUMERIC

RIGHT

LEFT

SOUNDEX

LEN

STUFF

LOWER

SUBSTRING

PATINDEX

UPPER