照合順序のサポート¶
照合では、文字列を比較するための代替ルールを指定できます。これを使用して、特定の言語または他のユーザー指定のルールに従ってデータを比較し、ソートします。
照合順序のサポートの概要¶
以下のセクションでは、照合順序とは何か、また文字列を比較するときに照合順序をどのように使用するかを説明します。
照合順序の理解¶
Snowflakeのテキスト文字列は UTF-8文字セットを使用して保存され、デフォルトでは、文字列内の文字を表すUnicodeコードに従って文字列が比較されます。
ただし、 UTF-8文字表現に基づいて文字列を比較すると、期待される/必要な動作が得られない場合があります。例:
特定の言語の特殊文字がその言語の順序付け基準に従って並べ替えられない場合、並べ替えは予期しない結果を返す可能性があります。
文字が大文字や小文字であることを無視するなど、他の規則に従って文字列を並べる場合があります。
照合を使用すると、以下に基づいて、文字列の比較に使用するルールを明示的に指定できます。
異なるロケール(異なる言語の異なる文字セット)。
大文字と小文字の区別(UPPER または LOWER 関数を明示的に呼び出して文字列を変換せずに、大文字と小文字を区別する、または大文字と小文字を区別しない文字列比較を使用する)。
アクセント記号の区別(
Z
、Ź
、Ż
などが同じ文字または異なる文字と見なされるかどうか)。句読点の区別(比較に文字のみを使用するか、すべての文字を含めるか)。たとえば、比較で句読点が区別されない場合、
A-B-C
とABC
は同等として扱われます。文字列の最初の文字に基づいた並べ替えの設定や、先頭および/または末尾の空白スペースのトリミングなどの追加オプション。
照合順序の用途¶
照合は、次のようなさまざまな操作で使用できます(ただし、これらに限定されません)。
使用法 |
例 |
リンク |
---|---|---|
簡単な比較 |
|
|
結合 |
|
|
並び替え |
|
|
Top-Kソート |
|
|
集計 |
|
|
ウィンドウ関数 |
|
|
スカラー関数 |
|
|
集計関数 |
|
|
データクラスタリング |
|
照合順序の制御¶
照合は細かく制御されます。使用する照合を次のように明示的に指定できます。
アカウントレベルのパラメーター DEFAULT_DDL_COLLATION を使用するアカウント。
ALTER DATABASE コマンドを使用して、データベースに追加されたすべてのテーブルのすべての列。
ALTER SCHEMA コマンドを使用して、スキーマに追加されたすべてのテーブルのすべての列。
ALTER TABLE コマンドを使用して、テーブルに追加されたすべての列。
CREATE TABLE コマンドを使用した、テーブル内の個々の列。
SQL ステートメント内の特定の比較(例:
WHERE col1 = col2
)。ステートメントに複数の照合が適用される場合、Snowflakeは優先順位に基づいて使用する照合を決定します。優先順位の詳細については、このトピック内の 複数文字列操作での照合順序の優先順位 をご参照ください。
照合順序の SQL 構造¶
照合順序には以下の SQL 構文を使用できます。
テーブル列定義の COLLATE 句¶
オプションの COLLATE 句をテーブル列の定義に追加すると、指定された照合順序が列内のデータに対して実行される比較およびその他の関連操作に使用されることが示されます。
CREATE TABLE <table_name> ( <col_name> <col_type> COLLATE '<collation_specification>'
[ , <col_name> <col_type> COLLATE '<collation_specification>' ... ]
[ , ... ]
)
列に COLLATE 句が指定されていない場合、Snowflakeはデフォルトを使用し、 UTF-8文字表現に基づいて文字列を比較します。
また、Snowflakeは、照合仕様で空の文字列(例: COLLATE ''
)の指定をサポートしています。これは、列に照合なしを指定するのと同等です。
ただし、優先順位により、列に COLLATE ''
を指定しても、 COLLATE 'utf8'
を明示的に指定した場合と同じ効果はありません。詳細については、 複数文字列操作での照合順序の優先順位 をご参照ください。
テーブルの列に照合が指定されているかどうかを確認するには、 DESCRIBE TABLE を使用します。または COLLATION 関数を使用して、特定の列の照合を表示します(存在する場合)。
COLLATE 関数¶
この COLLATE 関数は、入力文字列式で指定された照合順序を使用します。
COLLATE( <expression> , '<collation_specification>' )
中置記法を使用して、この関数を呼び出すこともできます。
<expression> COLLATE '<collation_specification>'
この関数は、特定の操作(並べ替えなど)に対して特定の照合を明示的に指定する場合に特に役立ちますが、次の目的にも使用できます。
サブクエリの SELECT 句で照合を許可し、外部クエリの指定された列に対するすべての操作で照合を使用します。
指定された照合で CTAS を使用してテーブルを作成します。
この例では、英語の大文字と小文字を区別しない照合順序を使用しています。
SELECT * FROM t1 WHERE COLLATE(col1 , 'en-ci') = 'Tango';
このコマンドは、ドイツ語の照合を使用して結果をソートしています。
SELECT * FROM t1 ORDER BY COLLATE(col1 , 'de');
この例では、フランス語の照合順序を使用した列を持つテーブルを作成します。
CREATE TABLE t2 AS SELECT COLLATE(col1, 'fr') AS col1 FROM t1;
この例では、infix記法を使用して、フランス語の照合順序を使用する列を持つテーブルを作成します。
CREATE TABLE t2 AS SELECT col1 COLLATE 'fr' AS col1 FROM t1;
COLLATION 関数¶
この COLLATION 関数は、テーブルの列を含む式で使用される照合順序仕様を返します。
COLLATION( <expression> )
式に照合順序が指定されていない場合、関数は NULL を返します。
通常、これを列名で使用する場合、 DISTINCT を使用して、テーブルの各行に対して出力の1行を取得しないようにします。例:
SELECT DISTINCT COLLATION(column1) FROM table1;
注釈
この関数は、優先順位レベルではなく、照合仕様のみを返します。優先順位の詳細については、このトピック内の 複数文字列操作での照合順序の優先順位 をご参照ください。
照合順序仕様¶
COLLATE 句(テーブル列の場合)または COLLATE 関数(式の場合)を使用する場合、列/式に使用される比較ロジックを決定する照合指定を含める必要があります。
照合仕様は、次の形式のハイフン(-
)で区切られた1つ以上の指定子の文字列で構成されます。
'<specifier>[-<specifier> ...]'
次の指定子がサポートされています(詳細については、このトピック内の サポートされている指定子 をご参照ください)。
ロケール
大文字と小文字の区別
アクセント記号の区別
句読点の区別
最初の文字の設定
大文字と小文字の変換
スペーストリミング
指定子は大文字と小文字を区別せず、使用する場合は常に最初にする必要があるロケールを除いて、任意の順序にすることができます。
次のセクションで、照合順序仕様についての詳細を説明します。
仕様例¶
照合仕様の文字列の例を次に示します。
'de'
:ドイツ語ロケール。'de-ci-pi'
:ドイツ語ロケール。大文字と小文字の区別なし、句読点の区別なしの比較。'fr_CA-ai'
:カナダフランス語ロケール。アクセント記号の区別なしの比較。'en_US-trim'
: US 英語ロケール。比較の前に先頭のスペースと末尾のスペースがトリミングされる比較。
照合仕様に空の文字列を指定することもでき(例: COLLATE ''
または COLLATE(col1, '')
)、これは照合を使用しないことを示します。
サポートされている指定子¶
- ロケール:
適用する言語および国の固有ルールを指定します。
language_country
の形式の言語コード(必須)と国コード(オプション)で構成される有効なロケール文字列をサポートします。ロケールの例を次に示します。en
- 英語en_US
- アメリカ英語fr
- フランス語fr_CA
- カナダフランス語
さらに、
utf8
疑似ロケールは、デフォルトではUnicode順序の使用を指定します。詳細については、 UTF-8 またはロケール照合順序を使用した場合の並べ替えの相違 (このトピック内)をご参照ください。ロケール指定子はオプションですが、使用する場合は、文字列の 最初の 指定子でなければなりません。
Snowflakeがサポートするロケールの全リストについては、 Snowflakeがサポートする照合ロケール をご参照ください。
- 大文字と小文字の区別:
値を比較する際に大文字と小文字を区別するかどうかを決定します。可能な値:
cs
- 大文字と小文字を区別する(デフォルト)ci
- 大文字と小文字を区別しない
例:
照合 仕様
値
結果
'en-ci'
Abc = abc
True
'en-cs'
/en
Abc = abc
False
- アクセント記号の区別:
アクセント記号付き文字を、その基本文字と同等とみなすか、異なる文字とみなすかを決定します。可能な値:
as
- アクセントト記号を区別する(デフォルト)ai
- アクセント記号を区別しない
例:
照合 仕様
値
結果
メモ
'fr-ai'
E = É
True
'fr-as'
/'fr'
E = É
False
'en-ai'
a = ą
True
英語では、これらの文字はアクセントの違いのみを持つものとして扱われるため、アカウントを区別しないように指定すると、値は等しいと比較されます。
'pl-ai'
a = ą
False
ポーランド語では、これらの文字は個別のベース文字として扱われるため、アクセントを区別しないように指定されているかどうかに関係なく、常に等しくないものとして比較されます。
'pl-as'
/'pl'
a = ą
False
アクセントの区別と照合の規則は言語に応じて異なります。例えば、一部の言語では照合は常にアクセントを区別するため、アクセントを区別しない照合を指定しても照合をオフにはできません。
- 句読点の区別:
文字以外の文字が重要かどうかを判断します。可能な値:
ps
- 句読点を区別します。pi
- 句読点を区別しません。
デフォルトはロケール固有になっています(句読点の区別が指定されていない場合、ロケール固有のルールが使用されます)。ほとんどの場合、ルールは
ps
と同等です。例:
照合 仕様
値
結果
メモ
'en-pi'
A-B-C = ABC
True
'en-ps'
A-B-C = ABC
False
- 最初の文字の設定:
並べ替えの際に、大文字を先にするか小文字を先にするかを決定します。可能な値:
fl
- 小文字が最初にソートされます。fu
- 大文字が最初にソートされます。
デフォルトはロケール固有になっています(値が指定されていない場合、ロケール固有の順序が使用されます)。ほとんどの場合、順序は
fl
と同等です。また、この指定子は等価比較に影響を与えません。
- 大文字と小文字の変換:
比較の前に文字列が小文字または大文字に変換されます。状況によっては、これはロケール固有の完全な照合よりも高速です。可能な値:
upper
- 比較の前に文字列を大文字に変換します。lower
- 比較の前に文字列を小文字に変換します。
この指定子にはデフォルトがありません(値が指定されていない場合、変換は行われません)。
- スペーストリミング:
比較の前に文字列の先頭/末尾のスペースを削除します。この機能は、セマンティクスで SQL CHAR データ型と同等の比較(非常にまれな場合を除く)を実行するのに役立ちます。
可能な値:
trim
- 比較の前に先頭と末尾の両方のスペースを削除します。ltrim
- 比較の前に先頭のスペースのみを削除します。rtrim
- 比較の前に末尾のスペースのみを削除します。
この指定子にはデフォルトがありません(値が指定されていない場合、トリミングは実行されません)。
例:
照合 仕様
値
結果
メモ
'en-trim'
__ABC_ = ABC
True
例を示すために、ここではアンダースコア文字は空白スペースを表しています。
'en-ltrim'
__ABC_ = ABC
False
'en-rtrim'
__ABC_ = ABC
False
'en'
__ABC_ = ABC
False
照合順序の実装の詳細¶
次のセクションで、照合順序のサポートについての詳細を説明します。
大文字と小文字を区別しない比較¶
以下のセクションでは、大文字と小文字を区別しない比較について説明します。
大文字の文字列と元の文字列を比較したときの相違¶
一部の言語では、2つの小文字と対応する大文字が同一である場合があります。たとえば、一部の言語は、ドット付きとドットなしの小文字 I
(例: i
と ı
)の両方をサポートします。文字列を大文字に強制すると、比較に影響します。
次の例は、その違いを示しています。
テーブルを作成します。
CREATE OR REPLACE TABLE test_table (col1 VARCHAR, col2 VARCHAR);
INSERT INTO test_table VALUES ('ı', 'i');
データをクエリします。
SELECT col1 = col2,
COLLATE(col1, 'lower') = COLLATE(col2, 'lower'),
COLLATE(col1, 'upper') = COLLATE(col2, 'upper')
FROM test_table;
+-------------+-------------------------------------------------+-------------------------------------------------+
| COL1 = COL2 | COLLATE(COL1, 'LOWER') = COLLATE(COL2, 'LOWER') | COLLATE(COL1, 'UPPER') = COLLATE(COL2, 'UPPER') |
|-------------+-------------------------------------------------+-------------------------------------------------|
| False | False | True |
+-------------+-------------------------------------------------+-------------------------------------------------+
文字の重み¶
Snowflakeは、次の 照合仕様 をサポートしています。
ICU (Unicode用の国際化コンポーネント)。
Snowflake固有の照合仕様(例:
upper
およびlower
)。
ICU で定義された大文字と小文字を区別しない比較操作の場合、Snowflakeは Unicode照合アルゴリズム(UCA) に従い、Unicode文字の3次の重みではなく、1次および2次の重みのみを考慮します。3次の重みのみが異なる文字は、同一として扱われます。たとえば、 en-ci
照合仕様を使用すると、スペースと改行なしスペースは同一であると見なされます。
UTF-8 またはロケール照合順序を使用した場合の並べ替えの相違¶
文字列は常に内部的にSnowflakeの UTF-8に保存され、 UTF-8でサポートされているすべての言語のすべての文字を表すことができます。したがって、デフォルトの照合順序は UTF-8 (すなわち 'utf8'
)です。
UTF-8照合は、文字のアルファベット順ではなく、文字の数値表現に基づいています。
これは、各 ASCII 文字を序数値で並べ替えることに似ています。大文字は序数値が小文字よりも小さいため、注意が必要です。
A = 65
B = 66
...
a = 97
b = 98
...
その結果:
UTF-8の順序で並べ替えると、すべての大文字がすべての小文字の前に返されます。
A
、B
、 ... 、Y
、Z
、 ... 、a
、b
、 ... 、y
、z
対照的に、
'en'
照合仕様は( UTF-8内部表現を使用する代わりに)アルファベット順に並べ替えられ、B
とb
の両方の前にA
とa
の両方が返されます。a
、A
、b
、B
、 ...
さらに、 cs
と ci
の大文字と小文字の区別指定子の違いは、並べ替えに影響します。
cs
(大文字と小文字を区別する)は、常に同じ文字の大文字バージョンの前に小文字バージョンの文字を返します。例えば、'en-cs'
を使用する場合:a
、A
、b
、B
、 ...デフォルトでは大文字と小文字が区別されるため、
'en-cs'
と'en'
は同等です。ci
(大文字と小文字を区別しない)は、大文字と小文字の文字を相互にランダムに返しますが、それ以降の大文字と小文字のバージョン両方の前になります。たとえば、'en-ci'
を使用する場合、A
、a
、b
、B
、 ...
一部のアルファベット以外の文字は、照合設定に応じて異なる方法でソートできます。次のコード例は、プラス文字(+
)とマイナス文字(-
)が、異なる照合設定に対して異なる方法でソートされていることを示しています。
テーブルを作成します。
CREATE OR REPLACE TABLE demo (
no_explicit_collation VARCHAR,
en_ci VARCHAR COLLATE 'en-ci',
en VARCHAR COLLATE 'en',
utf_8 VARCHAR collate 'utf8');
INSERT INTO demo (no_explicit_collation) VALUES
('-'),
('+');
UPDATE demo SET
en_ci = no_explicit_collation,
en = no_explicit_collation,
utf_8 = no_explicit_collation;
データをクエリします。
SELECT MAX(no_explicit_collation), MAX(en_ci), MAX(en), MAX(utf_8)
FROM demo;
+----------------------------+------------+---------+------------+
| MAX(NO_EXPLICIT_COLLATION) | MAX(EN_CI) | MAX(EN) | MAX(UTF_8) |
|----------------------------+------------+---------+------------|
| - | + | + | - |
+----------------------------+------------+---------+------------+
複数文字列操作での照合順序の優先順位¶
2つ(またはそれ以上)の文字列で操作を実行すると、異なる文字列に対して異なる照合が指定される場合があります。適用する照合の決定は、各入力に対して照合が指定された方法と、各指定子の優先順位によって異なります。
次の3つの優先レベルがあります(最高から最低まで)。
- 関数:
照合は、 SQL ステートメントで COLLATE 関数 関数を使用して指定されます。
- 列:
列の定義で照合が指定されました。
- なし:
特定の式/列に照合が指定されていない/使用されていなかったか、空の仕様を持つ照合が使用されている/使用されていた(
COLLATE(col1, '')
またはcol1 STRING COLLATE ''
など)。
使用する照合を決定するときに、優先順位が 最高 の照合仕様が使用されます。複数の照合が指定され、それらの優先レベルが同じ場合、それらの値が比較され、等しくない場合、エラーが返されます。
例えば、次の列レベルの照合仕様を持つテーブルについて考えます。
CREATE OR REPLACE TABLE collation_precedence_example(
col1 VARCHAR, -- equivalent to COLLATE ''
col2_fr VARCHAR COLLATE 'fr', -- French locale
col3_de VARCHAR COLLATE 'de' -- German locale
);
2つの文字列を比較するステートメントでテーブルが使用される場合、照合は次のように適用されます。
この比較では、
col2_fr
の優先順位がcol1
の優先順位より高いため、'fr'
照合順序を使用します。... WHERE col1 = col2_fr ...
この比較では、
'en'
の照合順序を使用します。これは、ステートメントで明示的に指定されているためで、col2_fr
の照合順序よりも優先されます。... WHERE col1 COLLATE 'en' = col2_fr ...
この比較は、式が同じ優先順位レベルで異なる照合を持つため、エラーを返します。
... WHERE col2_fr = col3_de ...
この比較では、
col2_fr
の照合順序が削除されたため、'de'
の照合順序を使用します。... WHERE col2_fr COLLATE '' = col3_de ...
この比較は、式が同じ優先順位レベルで異なる照合を持つため、エラーを返します。
... WHERE col2_fr COLLATE 'en' = col3_de COLLATE 'de' ...
Snowflakeのデフォルトの照合は 'utf8'
ですが、空の文字列を指定する(または照合なしを指定する)ことは、明示的な照合が照合なしよりも優先されるため、明示的に 'utf8'
を指定することとは異なります。以下のコード例の最後にあるステートメント2つに違いが示されています。
例えば、次の列レベルの照合仕様を持つテーブルについて考えます。
CREATE OR REPLACE TABLE collation_precedence_example2(
s1 STRING COLLATE '',
s2 STRING COLLATE 'utf8',
s3 STRING COLLATE 'fr'
);
2つの文字列を比較するステートメントでテーブルが使用される場合、照合は次のように適用されます。
s1
には照合順序がなく、'utf8'
がデフォルトであるため、この比較では'utf8'
を使用します。... WHERE s1 = 'a' ...
s1
には照合順序がなく、s2
には明示的な照合順序'utf8'
があるため、この比較では'utf8'
を使用します... WHERE s1 = s2 ...
s1
には照合順序がなく、s3
には明示的なfr
照合順序があるため、この例はエラーなしで実行され、明示的な照合順序が優先されます。... WHERE s1 = s3 ...
s2
、s3
、同じ優先度で指定された照合順序が異なるため、この比較はエラーとなります。... WHERE s2 = s3 ...
002322 (42846): SQL compilation error: Incompatible collations: 'fr' and 'utf8'
組み込み関数での照合順序の限定サポート¶
照合は、文字列関数のサブセットでのみサポートされています。照合を実装することが合理的に期待できるが、照合をまだサポートしていない関数は、照合で使用するとエラーを返します。これらのエラーメッセージは、 COLLATE 関数を呼び出すときだけでなく、その列を作成した CREATE TABLE または ALTER TABLE ステートメントで照合されると定義された列で文字列関数を呼び出すときにも表示されます。
現在、照合順序は、単純な比較操作にのみ影響します。たとえば、大文字と小文字を区別しない照合順序が指定されていても、 POSITION('abc' in COLLATE('ABC', 'en-ci'))
は ABC
で abc
を検出しません。
照合順序をサポートする関数¶
これらの関数は照合をサポートします。
これらの関数の一部には、照合での使用に制限があります。情報については、特定の各機能のドキュメントをご参照ください。
このリストは、経時的に拡大する可能性があります。
注意
||
(連結)や LIKE
などの一部の SQL 演算子および述語は、関数として実装されています(また、 LIKE()
や CONCAT()
などの関数として使用可能)。述語または演算子が関数として実装され、その関数が照合をサポートしていない場合、述語または演算子は照合をサポートしません。
照合順序の制限 もご参照ください。
照合順序の使用におけるパフォーマンスへの影響¶
照合の使用は、さまざまなデータベース操作のパフォーマンスに影響を与える可能性があります。
照合順序の使用に関する追加の考慮事項¶
名前が類似しているにもかかわらず、次の照合関数は異なる結果を返します。
照合仕様の列では、照合のロケールにない文字を使用できます。これは、並べ替えに影響する可能性があります。
例えば、列が
COLLATE 'en'
句で作成された場合、列のデータには英語以外の文字É
を含めることができます。この状況では、文字É
はE
の近くに並べ替えられます。意味のない場合がある照合操作を指定できます。
例えば、ドイツ語の照合を使用してポーランド語のデータをフランス語のデータと比較するように指定できます。
SELECT ... WHERE COLLATE(French_column, 'de') = Polish_column;
ただし、予期しない結果または意図しない結果を返す可能性があるため、この機能をこの方法で使用することをSnowflakeは 推奨しません 。
テーブルの列が定義されると、その列の照合順序は変更できません。つまり、 CREATE TABLE ステートメントを使用して特定の照合で列が作成された後、 ALTER TABLE を使用した照合の変更はできません。
ただし、列を参照する SELECT ステートメントなどの DML ステートメントで別の照合を指定できます。
ci
と upper
/ lower
の相違¶
upper
と lower
照合順序仕様は、文字列の比較とソート時に ci
照合順序仕様よりも良いパフォーマンスを提供することができます。しかし、 upper
と lower
には、次のセクションで説明するように、 ci
と若干異なる効果があります。
幅、スペース、スクリプトの比較の相違¶
文字列の比較の際、 ci
照合順序仕様は、文字の異なる視覚表現が同じ文字を指す可能性があることを認識し、それに従って扱います。より効率的な比較を可能にするために、 upper
と lower
の照合順序仕様は、文字のこれらの異なる視覚表現を同じ文字として認識しません。
具体的には、 ci
照合順序仕様は以下に挙げるいくつかのカテゴリの違いを無視しますが、 upper
と lower
の照合順序仕様はそれらを無視しません。
以下のセクションでは、これらの相違を説明する例を挙げています。
注釈
全角文字と半角文字の比較動作はロケールに依存する可能性があります。
幅の異なる文字の比較例¶
different_widths
という名前のテーブルを作成し、異なる幅の文字を含む行を挿入します。
CREATE OR REPLACE TABLE different_widths(codepoint STRING, description STRING);
INSERT INTO different_widths VALUES
('a', 'ASCII a'),
('A', 'ASCII A'),
('a', 'Full-width a'),
('A', 'Full-width A');
SELECT codepoint VISUAL_CHAR,
'U+' || TO_CHAR(UNICODE(codepoint), '0XXX') codepoint_representation,
description
FROM different_widths;
+-------------+--------------------------+--------------+
| VISUAL_CHAR | CODEPOINT_REPRESENTATION | DESCRIPTION |
|-------------+--------------------------+--------------|
| a | U+0061 | ASCII a |
| A | U+0041 | ASCII A |
| a | U+FF41 | Full-width a |
| A | U+FF21 | Full-width A |
+-------------+--------------------------+--------------+
次のクエリは、 ci
照合順序仕様が、文字を比較する際に1つの異なる値を検出することを示しています。 upper
と lower
の照合順序仕様は、文字を比較する際に2つの異なる値を検索します。
SELECT COUNT(*) NumRows,
COUNT(DISTINCT UNICODE(codepoint)) DistinctCodepoints,
COUNT(DISTINCT codepoint COLLATE 'en-ci') DistinctCodepoints_EnCi,
COUNT(DISTINCT codepoint COLLATE 'upper') DistinctCodepoints_Upper,
COUNT(DISTINCT codepoint COLLATE 'lower') DistinctCodepoints_Lower
FROM different_widths;
+---------+--------------------+-------------------------+--------------------------+--------------------------+
| NUMROWS | DISTINCTCODEPOINTS | DISTINCTCODEPOINTS_ENCI | DISTINCTCODEPOINTS_UPPER | DISTINCTCODEPOINTS_LOWER |
|---------+--------------------+-------------------------+--------------------------+--------------------------|
| 4 | 4 | 1 | 2 | 2 |
+---------+--------------------+-------------------------+--------------------------+--------------------------+
ci
照合順序仕様は幅と大文字小文字の相違を無視します。 upper
と lower
の照合順序仕様は大文字小文字の相違を無視するのみであり、半角文字は全角文字とは異なる文字とみなされます。
半角小文字 a
は半角大文字 A
と同じとみなされ、全角小文字 a
は全角大文字 A
と同じとみなされます。したがって、 upper
と lower
の照合順序仕様では、2つの異なる値が検出されます。
異なるタイプのスペースの比較例¶
different_whitespaces
という名前のテーブルを作成し、異なるタイプのスペースを持つ行を挿入します。
CREATE OR REPLACE TABLE different_whitespaces(codepoint STRING, description STRING);
INSERT INTO different_whitespaces VALUES
(' ', 'ASCII space'),
('\u00A0', 'Non-breaking space'),
(' ', 'Ogham space mark'),
(' ', 'en space'),
(' ', 'em space');
SELECT codepoint visual_char,
'U+' || TO_CHAR(unicode(codepoint), '0XXX')
codepoint_representation, description
FROM different_whitespaces;
+-------------+--------------------------+--------------------+
| VISUAL_CHAR | CODEPOINT_REPRESENTATION | DESCRIPTION |
|-------------+--------------------------+--------------------|
| | U+0020 | ASCII space |
| | U+00A0 | Non-breaking space |
| | U+1680 | Ogham space mark |
| | U+2002 | en space |
| | U+2003 | em space |
+-------------+--------------------------+--------------------+
次のクエリは、 ci
照合順序仕様が、スペースを比較するときに1つの明確な値を検出することを示しています。 upper
と lower
の照合順序仕様では、スペースを比較する際に5つの異なる値が検出されます。
SELECT COUNT(*) NumRows,
COUNT(DISTINCT UNICODE(codepoint)) NumDistinctCodepoints,
COUNT(DISTINCT codepoint COLLATE 'en-ci') DistinctCodepoints_EnCi,
COUNT(DISTINCT codepoint COLLATE 'upper') DistinctCodepoints_Upper,
COUNT(DISTINCT codepoint COLLATE 'lower') DistinctCodepoints_Lower
FROM different_whitespaces;
+---------+-----------------------+-------------------------+--------------------------+--------------------------+
| NUMROWS | NUMDISTINCTCODEPOINTS | DISTINCTCODEPOINTS_ENCI | DISTINCTCODEPOINTS_UPPER | DISTINCTCODEPOINTS_LOWER |
|---------+-----------------------+-------------------------+--------------------------+--------------------------|
| 5 | 5 | 1 | 5 | 5 |
+---------+-----------------------+-------------------------+--------------------------+--------------------------+
異なるスクリプトを持つ文字の比較例¶
different_scripts
という名前のテーブルを作成し、異なるスクリプトを使用する文字を含む行を挿入します。
CREATE OR REPLACE TABLE different_scripts(codepoint STRING, description STRING);
INSERT INTO different_scripts VALUES
('1', 'ASCII digit 1'),
('¹', 'Superscript 1'),
('₁', 'Subscript 1'),
('①', 'Circled digit 1'),
('੧', 'Gurmukhi digit 1'),
('௧', 'Tamil digit 1');
SELECT codepoint VISUAL_CHAR,
'U+' || TO_CHAR(UNICODE(codepoint), '0XXX') codepoint_representation,
description
FROM different_scripts;
+-------------+--------------------------+------------------+
| VISUAL_CHAR | CODEPOINT_REPRESENTATION | DESCRIPTION |
|-------------+--------------------------+------------------|
| 1 | U+0031 | ASCII digit 1 |
| ¹ | U+00B9 | Superscript 1 |
| ₁ | U+2081 | Subscript 1 |
| ① | U+2460 | Circled digit 1 |
| ੧ | U+0A67 | Gurmukhi digit 1 |
| ௧ | U+0BE7 | Tamil digit 1 |
+-------------+--------------------------+------------------+
次のクエリは、 ci
照合順序仕様が文字を比較する際に1つの明確な値を検出することを示しています。 upper
と lower
の照合順序仕様では、文字を比較する際に6つの異なる値が検出されます。
SELECT COUNT(*) NumRows,
COUNT(DISTINCT UNICODE(codepoint)) DistinctCodepoints,
COUNT(DISTINCT codepoint COLLATE 'en-ci') DistinctCodepoints_EnCi,
COUNT(DISTINCT codepoint COLLATE 'upper') DistinctCodepoints_Upper,
COUNT(DISTINCT codepoint COLLATE 'lower') DistinctCodepoints_Lower
FROM different_scripts;
+---------+--------------------+-------------------------+--------------------------+--------------------------+
| NUMROWS | DISTINCTCODEPOINTS | DISTINCTCODEPOINTS_ENCI | DISTINCTCODEPOINTS_UPPER | DISTINCTCODEPOINTS_LOWER |
|---------+--------------------+-------------------------+--------------------------+--------------------------|
| 6 | 6 | 1 | 6 | 6 |
+---------+--------------------+-------------------------+--------------------------+--------------------------+
無視できるコードポイントの処理の相違¶
Unicode照合順序アルゴリズムは、照合順序要素(コードポイント)は 無視できる と指定しており、これは文字列の比較と並べ替えの際にコードポイントが考慮されないことを意味します。
ci
照合順序仕様により、これらのコードポイントは無視されます。このため、無視できるコードポイントの検索や置換が困難になる可能性があります。upper
とlower
の照合順序仕様では、これらのコードポイントは無視されません。
たとえば、コードポイント U+0001
は無視できます。このコードポイントを en-ci
照合順序指定で空文字列と比較すると、 U+0001
は無視されるため、結果は TRUE になります。
SELECT '\u0001' = '' COLLATE 'en-ci';
+-------------------------------+
| '\U0001' = '' COLLATE 'EN-CI' |
|-------------------------------|
| True |
+-------------------------------+
一方、 upper
または lower
照合順序仕様を使用する場合、 U+0001
は無視されないため、結果は FALSE になります。
SELECT '\u0001' = '' COLLATE 'upper';
+-------------------------------+
| '\U0001' = '' COLLATE 'UPPER' |
|-------------------------------|
| False |
+-------------------------------+
同様に、文字列からこのコードポイントを削除するために REPLACE 関数を呼び出すとします。 en-ci
照合順序仕様を使用する場合、 U+0001
は無視されるため、この関数はコードポイントを削除しません。
以下の例に示すように、 REPLACE 関数が返す文字列は、関数が U+0001
文字を削除しないため、関数に渡された文字列と同じ長さです。
SELECT
LEN('abc\u0001') AS original_length,
LEN(REPLACE('abc\u0001' COLLATE 'en-ci', '\u0001')) AS length_after_replacement;
+-----------------+--------------------------+
| ORIGINAL_LENGTH | LENGTH_AFTER_REPLACEMENT |
|-----------------+--------------------------|
| 4 | 4 |
+-----------------+--------------------------+
一方、照合順序に upper
または lower
照合順序仕様を使用する場合、この関数は文字列からコードポイントを削除し、より短い文字列を返します。
SELECT
LEN('abc\u0001') AS original_length,
LEN(REPLACE('abc\u0001' COLLATE 'upper', '\u0001')) AS length_after_replacement;
+-----------------+--------------------------+
| ORIGINAL_LENGTH | LENGTH_AFTER_REPLACEMENT |
|-----------------+--------------------------|
| 4 | 3 |
+-----------------+--------------------------+
異なるコードポイントで文字が表現されている場合の相違¶
Unicodeでは、 異なるコードポイント列が同じ文字を表すことができます。たとえば、DialytikaとTonosのあるギリシャ小文字イオタは、コードポイント U+0390
のある 合成済み文字 、または分解済み文字のコードポイント U+03b9
U+0308
U+0301
のシーケンスで表すことができます。
ci
照合順序仕様を使用する場合、1つの文字に対する異なるコードポイントシーケンスは同じ文字として扱われます。たとえば、コードポイント U+0390
とコードポイント U+03b9
U+0308
U+0301
のシーケンスは等価として扱われます。
SELECT '\u03b9\u0308\u0301' = '\u0390' COLLATE 'en-ci';
+-------------------------------------------------+
| '\U03B9\U0308\U0301' = '\U0390' COLLATE 'EN-CI' |
|-------------------------------------------------|
| True |
+-------------------------------------------------+
upper
と lower
照合順序仕様のパフォーマンスを向上させるために、シーケンスは同じようには扱われません。2つのコードポイントのシーケンスは、大文字または小文字に変換された後に同じバイナリ表現になる場合にのみ、等価とみなされます。
たとえば、 upper
仕様をコードポイント U+0390
とコードポイント U+03b9
U+0308
U+0301
のシーケンスと合わせて使用すると、等価として扱われます。
SELECT '\u03b9\u0308\u0301' = '\u0390' COLLATE 'upper';
+-------------------------------------------------+
| '\U03B9\U0308\U0301' = '\U0390' COLLATE 'UPPER' |
|-------------------------------------------------|
| True |
+-------------------------------------------------+
lower
仕様を使用すると、文字は不等価になります。
SELECT '\u03b9\u0308\u0301' = '\u0390' COLLATE 'lower';
+-------------------------------------------------+
| '\U03B9\U0308\U0301' = '\U0390' COLLATE 'LOWER' |
|-------------------------------------------------|
| False |
+-------------------------------------------------+
このような相違は、 upper
(lower
ではなく)を使用すると、こうした相違が発生する可能性が小さくなります。これは、小文字の合成コードポイントが100個以上ある場合に比べて、大文字の合成コードポイントは1個(U+0130
)しかないためです。
単一文字を表すコードポイントのシーケンスとの相違¶
コードポイントのシーケンスが単一文字を表す場合、 ci
照合順序仕様は、シーケンスが単一文字を表すことを認識し、シーケンス内の個々のコードポイントを一致させません。
たとえば、コードポイント U+03b9
U+0308
U+0301
のシーケンスは単一文字(DialytikaとTonosのあるギリシャ小文字イオタと)を表します。 U+0308
と U+0301
は、 U+03b9
に適用されるアクセントを表します。
ci
照合順序仕様の場合、シーケンス U+03b9
U+0308
が U+03b9
または U+0308
を含むかどうかを判断するために CONTAINS 関数を使用すると、 U+03b9
U+0308
シーケンスは単一文字として扱われるため、関数は FALSE を返します。
SELECT CONTAINS('\u03b9\u0308', '\u03b9' COLLATE 'en-ci');
+----------------------------------------------------+
| CONTAINS('\U03B9\U0308', '\U03B9' COLLATE 'EN-CI') |
|----------------------------------------------------|
| False |
+----------------------------------------------------+
SELECT CONTAINS('\u03b9\u0308', '\u0308' COLLATE 'en-ci');
+----------------------------------------------------+
| CONTAINS('\U03B9\U0308', '\U0308' COLLATE 'EN-CI') |
|----------------------------------------------------|
| False |
+----------------------------------------------------+
パフォーマンスを向上させるために、 upper
と lower
仕様はこれらのシーケンスを単一文字として扱いません。上記の例では、 CONTAINS 関数は TRUE を返しますが、これはこれらの仕様が一連のコードポイントを別々の文字として扱っているからです。
SELECT CONTAINS('\u03b9\u0308', '\u03b9' COLLATE 'upper');
+----------------------------------------------------+
| CONTAINS('\U03B9\U0308', '\U03B9' COLLATE 'UPPER') |
|----------------------------------------------------|
| True |
+----------------------------------------------------+
SELECT CONTAINS('\u03b9\u0308', '\u0308' COLLATE 'upper');
+----------------------------------------------------+
| CONTAINS('\U03B9\U0308', '\U0308' COLLATE 'UPPER') |
|----------------------------------------------------|
| True |
+----------------------------------------------------+
大文字と小文字の変更が複数のコードポイントになる場合の相違¶
いくつかの合成文字では、大文字または小文字のバージョンがコードポイントのシーケンスで表されます。たとえば、ドイツ語の「ß」の大文字は、2つのS文字(SS)のシーケンスです。
ßと SS は等価であるにもかかわらず、 upper
照合順序仕様を使用すると、ßと SS の検索結果は異なります。大文字と小文字の変換によって生成されたシーケンスは、その全体が一致するか、まったく一致しないかのいずれかです。
SELECT CONTAINS('ß' , 's' COLLATE 'upper');
+--------------------------------------+
| CONTAINS('SS' , 'S' COLLATE 'UPPER') |
|--------------------------------------|
| False |
+--------------------------------------+
SELECT CONTAINS('ss', 's' COLLATE 'upper');
+-------------------------------------+
| CONTAINS('SS', 'S' COLLATE 'UPPER') |
|-------------------------------------|
| True |
+-------------------------------------+
並べ替え順序の相違¶
upper
と lower
照合順序仕様の並べ替えは、 ci
仕様の並べ替えとは動作が異なります。
ci
仕様では、文字列は照合順序キーで並べ替えられます。一般的に、照合順序キーは大文字と小文字の区別、アクセントの区別、ロケールなどを考慮することができます。upper
とlower
仕様では、パフォーマンスを向上させるために、文字列はコードポイントで並べ替えられます。
たとえば、 ASCII の範囲にある文字(+
や -
など)は並べ替えが異なります。
SELECT '+' < '-' COLLATE 'en-ci';
+---------------------------+
| '+' < '-' COLLATE 'EN-CI '|
|---------------------------|
| False |
+---------------------------+
SELECT '+' < '-' COLLATE 'upper';
+---------------------------+
| '+' < '-' COLLATE 'UPPER' |
|---------------------------|
| True |
+---------------------------+
別の例として、コードポイントを無視した文字列は異なる順序で並べ替えられます。
SELECT 'a\u0001b' < 'ab' COLLATE 'en-ci';
+-----------------------------------+
| 'A\U0001B' < 'AB' COLLATE 'EN-CI' |
|-----------------------------------|
| False |
+-----------------------------------+
SELECT 'a\u0001b' < 'ab' COLLATE 'upper';
+-----------------------------------+
| 'A\U0001B' < 'AB' COLLATE 'UPPER' |
|-----------------------------------|
| True |
+-----------------------------------+
さらに、絵文字の並べ替えも異なります。
SELECT 'abc' < '❄' COLLATE 'en-ci';
+-----------------------------+
| 'ABC' < '❄' COLLATE 'EN-CI' |
|-----------------------------|
| False |
+-----------------------------+
SELECT 'abc' < '❄' COLLATE 'upper';
+-----------------------------+
| 'ABC' < '❄' COLLATE 'UPPER' |
|-----------------------------|
| True |
+-----------------------------+
照合順序の制限¶
照合準には、次の制限が適用されます。
照合順序は、最大 8 MB の文字列に対してのみサポートされます¶
Snowflake VARCHAR データ型は最大 16 MB の文字列をサポートしますが、Snowflakeは 結果の 文字列が 8 MB 以下の場合にのみ照合をサポートします。(一部の照合操作では、文字列が長くなる場合があります。)
UDFs では照合順序はサポートされません¶
Snowflakeは、 UDFs (ユーザー定義関数)との照合をサポートしていません。
UDF からは、照合された文字列値を返すことはできません。サーバーは、実際の戻り型が宣言された戻り型と互換性のない場合にエラーを発生します。
照合された文字列値を UDF に渡す場合、照合情報は渡されません。UDF は、文字列を照合されていない文字列と見なします。
VARIANT 、 ARRAY、または OBJECT の文字列に対する照合順序はサポートされません¶
VARIANT 、 OBJECT 、または ARRAY 内に格納されている文字列には、照合仕様が含まれていません。したがって、次のようになります。
これらの値の比較では、常に
'utf8'
照合順序が使用されます。照合仕様を持つ VARCHAR 値を使用して、 ARRAY、 OBJECT、または VARIANT 値を構成する場合、照合仕様は保持されません。
ユーザーは値を抽出し、 VARCHAR にキャストし、照合仕様を追加することで、 ARRAY、 OBJECT、または VARIANT 内に格納されている値を比較できます。例:
COLLATE(VARIANT_COL:fld1::VARCHAR, 'en-ci') = VARIANT_COL:fld2::VARCHAR
照合順序例¶
次のステートメントは、列ごとに異なる照合を使用するテーブルを作成します。
CREATE OR REPLACE TABLE collation_demo (
uncollated_phrase VARCHAR,
utf8_phrase VARCHAR COLLATE 'utf8',
english_phrase VARCHAR COLLATE 'en',
spanish_phrase VARCHAR COLLATE 'es');
INSERT INTO collation_demo (
uncollated_phrase,
utf8_phrase,
english_phrase,
spanish_phrase)
VALUES (
'pinata',
'pinata',
'pinata',
'piñata');
注釈
照合順序は、格納できる文字のセットには影響しません。Snowflakeは、 UTF-8文字をすべてサポートしています。
表の次のクエリは、期待される値を示しています。
SELECT * FROM collation_demo;
+-------------------+-------------+----------------+----------------+
| UNCOLLATED_PHRASE | UTF8_PHRASE | ENGLISH_PHRASE | SPANISH_PHRASE |
|-------------------+-------------+----------------+----------------|
| pinata | pinata | pinata | piñata |
+-------------------+-------------+----------------+----------------+
次のクエリは、文字 ñ
が n
と一致しないため、一致を検出しません。
SELECT * FROM collation_demo WHERE spanish_phrase = uncollated_phrase;
+-------------------+-------------+----------------+----------------+
| UNCOLLATED_PHRASE | UTF8_PHRASE | ENGLISH_PHRASE | SPANISH_PHRASE |
|-------------------+-------------+----------------+----------------|
+-------------------+-------------+----------------+----------------+
照合順序を変更しても、関連する(ただし等しくはない)文字( ñ
と n
など)を強制的に等しいものとして処理します。
CREATE OR REPLACE TABLE collation_demo1 (
uncollated_phrase VARCHAR,
utf8_phrase VARCHAR COLLATE 'utf8',
english_phrase VARCHAR COLLATE 'en-ai',
spanish_phrase VARCHAR COLLATE 'es-ai');
INSERT INTO collation_demo1 (
uncollated_phrase,
utf8_phrase,
english_phrase,
spanish_phrase)
VALUES (
'piñata',
'piñata',
'piñata',
'piñata');
SELECT uncollated_phrase = 'pinata',
utf8_phrase = 'pinata',
english_phrase = 'pinata',
spanish_phrase = 'pinata'
FROM collation_demo1;
+------------------------------+------------------------+---------------------------+---------------------------+
| UNCOLLATED_PHRASE = 'PINATA' | UTF8_PHRASE = 'PINATA' | ENGLISH_PHRASE = 'PINATA' | SPANISH_PHRASE = 'PINATA' |
|------------------------------+------------------------+---------------------------+---------------------------|
| False | False | True | False |
+------------------------------+------------------------+---------------------------+---------------------------+
英語フレーズのみが次の理由で True
を返す可能性があります。
非連結の比較はアクセントを無視しません。
utf8
照合比較はアクセントを無視しません。en-ai
とes-ai
の照合比較ではアクセント記号は無視されますが、スペイン語ではñ
はアクセント記号付きのn
ではなく、個々の文字として扱われます。
以下の例は、並べ替え順に対する照合の効果を示しています。
INSERT INTO collation_demo (spanish_phrase) VALUES
('piña colada'),
('Pinatubo (Mount)'),
('pint'),
('Pinta');
SELECT spanish_phrase FROM collation_demo
ORDER BY spanish_phrase;
+------------------+
| SPANISH_PHRASE |
|------------------|
| Pinatubo (Mount) |
| pint |
| Pinta |
| piña colada |
| piñata |
+------------------+
次のクエリは、照合順序を 'es'
(スペイン語) から 'utf8'
に変更することで、異なる順序で値を返します。
SELECT spanish_phrase FROM collation_demo
ORDER BY COLLATE(spanish_phrase, 'utf8');
+------------------+
| SPANISH_PHRASE |
|------------------|
| Pinatubo (Mount) |
| Pinta |
| pint |
| piña colada |
| piñata |
+------------------+
この例は、 COLLATION 関数を使用して、列などの式の照合を表示する方法を示しています。
CREATE OR REPLACE TABLE collation_demo2 (
c1 VARCHAR COLLATE 'fr',
c2 VARCHAR COLLATE '');
INSERT INTO collation_demo2 (c1, c2) VALUES
('a', 'a'),
('b', 'b');
SELECT DISTINCT COLLATION(c1), COLLATION(c2) FROM collation_demo2;
+---------------+---------------+
| COLLATION(C1) | COLLATION(C2) |
|---------------+---------------|
| fr | NULL |
+---------------+---------------+
DESCRIBE TABLE を使用して、テーブルの列に関する照合情報を表示することもできます。
DESC TABLE collation_demo2;
+------+--------------------------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+
| name | type | kind | null? | default | primary key | unique key | check | expression | comment | policy name | privacy domain |
|------+--------------------------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------|
| C1 | VARCHAR(16777216) COLLATE 'fr' | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| C2 | VARCHAR(16777216) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
+------+--------------------------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+