Oracle Database の文字列比較のデフォルト値は初期化パラメーター NLS_SORTとNLS_COMPで決まります。どちらのパラメーターもデフォルト値はBINARYで、WHERE句の比較やソート時にはバイナリ比較(大文字/小文字を異なるものとみなす)が使われます。
ソート順の指定には末尾に _CI を付けると大文字と小文字を区別せず、_AI を付けるアクセント記号も区別しません。
COLLATION指定
Oracle Database 12cではこの設定をテーブル単位、列単位で指定できるようになりました。
テーブル単位の指定
下記の例はcollation1テーブルのデフォルトのCollationをBINARY_CIに指定しています。
SQL> CREATE TABLE collation1 (c1 NUMBER, c2 VARCHAR2(10)) DEFAULT COLLATION BINARY_CI ;
表が作成されました。
列単位の指定
列単位に指定する場合は、列定義にCOLLATE句を指定します。
SQL> CREATE TABLE collation2 (c1 VARCHAR2(10), c2 VARCHAR2(10) COLLATE BINARY_CI) ;
表が作成されました。
SQL> INSERT INTO collation2 VALUES ('ABC', 'ABC') ;
1行が作成されました。
SQL> INSERT INTO collation2 VALUES ('abc', 'abc') ;
1行が作成されました。
上記の例では、WHERE句の指定方法によって取得できるデータが変わります。最初の例ではCOLLATE BINARYが指定されているので大文字と小文字は区別されます。次の例では COLLATE BINARY_CIが指定されているので大文字と小文字は区別されません。
SQL> SELECT * FROM collation2 WHERE c1='ABC' ;
C1 C2
---------- ----------
ABC ABC
SQL> SELECT * FROM collation2 WHERE c2='ABC' ;
C1 C2
---------- ----------
ABC ABC
abc abc
実行計画を確認してみる
実行計画を見ると、COLLATE指定された列に対する検索ではNLS_SORT関数が自動的に実行されていることがわかります。
SQL> SELECT * FROM collation2 WHERE c2='ABC' ;
C1 C2
---------- ----------
ABC ABC
abc abc
実行計画
----------------------------------------------------------
Plan hash value: 3491307740
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 14 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| COLLATION2 | 1 | 14 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NLSSORT("C2",'nls_sort=''BINARY_CI''')=HEXTORAW('61626300'))
COLLATION設定が異なる列の結合
COLLATION設定が異なる列では単純に結合できません。
SQL> CREATE TABLE collation3 (c1 VARCHAR2(10), c2 VARCHAR2(10) COLLATE BINARY_CI) ;
表が作成されました。
SQL> CREATE TABLE collation4 (c1 VARCHAR2(10), c2 VARCHAR2(10) COLLATE BINARY_AI) ;
表が作成されました。
SQL> SELECT * FROM collation3 ci INNER JOIN collation4 ai ON ci.c2 = ai.c2 ;
SELECT * FROM collation3 ci INNER JOIN collation4 ai ON ci.c2 = ai.c2
*
行1でエラーが発生しました。:
ORA-43915: 照合を決定できません: 引数に競合する照合があります
WHERE句にCOLLATE句を使って同じ照合順序で比較するようにしてください。
SQL> SELECT * FROM collation3 ci INNER JOIN collation4 ai ON ci.c2 = ai.c2 COLLATE BINARY_CI ;
レコードが選択されませんでした。
実行計画
----------------------------------------------------------
Plan hash value: 377530914
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 28 | 4 (0)| 00:00:01|
|* 1 | HASH JOIN | | 1 | 28 | 4 (0)| 00:00:01|
| 2 | TABLE ACCESS FULL| COLLATION3 | 1 | 14 | 2 (0)| 00:00:01|
| 3 | TABLE ACCESS FULL| COLLATION4 | 1 | 14 | 2 (0)| 00:00:01|
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access(NLSSORT("CI"."C2",'nls_sort=''BINARY_CI''')=NLSSORT("AI"."C2" COLLATE "BINARY_CI",'nls_sort=''BINARY_CI'''))