Oracleでの大文字と小文字を区別しない検索


228

LIKEおよびその他の比較演算子=などのデフォルトの動作では、大文字と小文字が区別されます。

大文字と小文字を区別しないようにすることは可能ですか?


user_nameにインデックスが存在する場合でも、一部のサンプル検索では全表スキャンが行われることを覚えておいてください。
JonSG、2011年

8
REGEXP_LIKE(username,'me','i')LIKEの代わりに使用することを検討しましたか?
kubanczyk

5
いいえ、LIKEは問題なく動作します
sergionni 2012

回答:


82

10gR2以降、Oracleでは、NLS_COMPおよびNLS_SORTパラメータを設定することにより、文字列比較の動作を微調整できます。

SQL> SET HEADING OFF
SQL> SELECT *
  2  FROM NLS_SESSION_PARAMETERS
  3  WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

NLS_SORT
BINARY

NLS_COMP
BINARY


SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
  2  FROM DUAL;

         0

SQL>
SQL> ALTER SESSION SET NLS_COMP=LINGUISTIC;

Session altered.

SQL> ALTER SESSION SET NLS_SORT=BINARY_CI;

Session altered.

SQL>
SQL> SELECT *
  2  FROM NLS_SESSION_PARAMETERS
  3  WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

NLS_SORT
BINARY_CI

NLS_COMP
LINGUISTIC


SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
  2  FROM DUAL;

         1

大文字と小文字を区別しないインデックスを作成することもできます。

create index
   nlsci1_gen_person
on
   MY_PERSON
   (NLSSORT
      (PERSON_LAST_NAME, 'NLS_SORT=BINARY_CI')
   )
;

この情報は、Oracleの大文字と小文字を区別しない検索から取得されました。記事は言及してREGEXP_LIKEいますが、古き良き=ものでも動作するようです。


10gR2より古いバージョンでは実際には実行できません。アクセント記号を区別しない検索が必要でない場合、通常のアプローチUPPER()は列と検索式の両方を使用することです。


1
これはうまく機能しますが、LIKE / =演算子を使用した更新が非常に遅くなります...... :(
Saqib Ali

1
@SaqibAli任意のLIKE式(例:)WHERE foo LIKE '%abc%'は、インデックス化できない場合はすでに十分に遅く、大文字と小文字の区別に特に関係があるとは思われません。
アルバロ・ゴンサレス

1
シェル環境のように、SQLPLUSの外部でこれらを設定することもできます。たとえばを使用するPerlスクリプトでは、`DBI-> connect`を呼び出す前にDBD::Oracle書き込むことができます$ENV{NLS_SORT} = 'BINARY_CI'; $ENV{NLS_COMP} = 'LINGUISTIC';
mivk 2017

こんにちはALTER SESSION、修正のローカルインスタンスを変更するだけで、現在のセッションのように、つまり、いったん閉じて再び開くとリセットされます。現在の値が何であるかを確認できる方法はありますか?それがどこにでも保持されている場合、元の設定に戻すことができます...
Seabizkit

305

フルテキストインデックスを使用せずにOracleで大文字と小文字を区別しない検索を実行するには、主に3つの方法があります。

最終的にどの方法を選択するかは、個々の状況によって異なります。覚えておくべき主なことは、パフォーマンスを向上させるには、大文字と小文字を区別しない検索のために正しくインデックスを付ける必要があるということです。

1.列と文字列を同じように大文字小文字を区別します。

UPPER()またはを使用して、すべてのデータを強制的に同じケースにすることができますLOWER()

select * from my_table where upper(column_1) = upper('my_string');

または

select * from my_table where lower(column_1) = lower('my_string');

column_1索引付けされていない場合upper(column_1)またはのlower(column_1)、必要に応じて、これにより全表スキャンが強制される可能性があります。これを回避するために、関数ベースのインデックスを作成できます。

create index my_index on my_table ( lower(column_1) );

LIKEを使用している%場合は、検索する文字列の前後にを連結する必要があります。

select * from my_table where lower(column_1) LIKE lower('my_string') || '%';

このSQL Fiddleは、これらすべてのクエリで何が起こるかを示しています。インデックスがいつ使用され、いつ使用されないかを示すExplain Planに注意してください。

2.正規表現を使用します。

Oracle 10g以降 REGEXP_LIKE()が利用可能です。'i'大文字と小文字を区別しない検索を実行するために、_match_parameter_を指定できます。

これを等価演算子として使用するには、文字列の開始と終了を指定する必要があります。これは、カラットとドル記号で示されます。

select * from my_table where regexp_like(column_1, '^my_string$', 'i');

LIKEと同等の機能を実行するために、これらを削除できます。

select * from my_table where regexp_like(column_1, 'my_string', 'i');

ストリングには正規表現エンジンによって異なる解釈がされる文字が含まれている可能性があるため、これには注意してください。

このSQLフィドルは、REGEXP_LIKE()を使用することを除いて、同じ出力例を示しています。

3.セッションレベルで変更します。

NLS_SORTのパラメータは、発注を含む様々な比較演算子のための照合順序支配=とLIKEを。セッションを変更することにより、大文字と小文字を区別せずにバイナリを指定できます。つまり、そのセッションで実行されるすべてのクエリは、大文字と小文字を区別しないパラメーターを実行します。

alter session set nls_sort=BINARY_CI

周りにはたくさんの追加情報があります 別の言語を指定する場合や、BINARY_AIを使用してアクセントを区別しない検索を行う場合は、言語ソートと文字列検索ます。

また、NLS_COMPパラメータを変更する必要があります。引用する:

NLS_SORTパラメータに従う正確な演算子とクエリ句は、NLS_COMPパラメータの値によって異なります。演算子または句がNLS_COMPによって決定されるNLS_SORT値に従わない場合、使用される照合はBINARYです。

NLS_COMPのデフォルト値はBINARYです。ただし、LINGUISTICは、OracleがNLS_SORTの値に注意を払う必要があることを指定しています。

WHERE句およびPL / SQLブロック内のすべてのSQL操作の比較では、NLS_SORTパラメータで指定された言語ソートを使用する必要があります。パフォーマンスを向上させるために、言語比較を行う列に言語インデックスを定義することもできます。

したがって、もう一度、セッションを変更する必要があります

alter session set nls_comp=LINGUISTIC

ドキュメントに記載されているように、パフォーマンスを改善するために言語インデックスを作成することができます

create index my_linguistc_index on my_table 
   (NLSSORT(column_1, 'NLS_SORT = BINARY_CI'));

「関数ベースのインデックスを作成する」これがどんな違いをもたらすことができるかを驚くべき
Jacob Goulden

select * from my_table where lower(column_1) LIKE lower('my_string') || '%';代わり にやるのがなぜ違うのか尋ねてもいい select * from my_table where lower(column_1) LIKE lower('my_string%');ですか?メリットはありますか?
lopezvit 2016年

1
1つの理由は、クエリがパラメーター化されている場合(ほとんどの場合)、呼び出し側のコードが必ずしも@lopezvitの最後に%を連結する必要がない場合です。
Ben

1
の結果を台無しにするいくつかの文字がある場合、そのregexp_likeような文字列をエスケープする方法はありますか?たとえば、文字列に$が含まれている場合、出力は期待したものとは異なります。// cc @Benと他の人が共有してください。
bozzmob 2016

2
` エスケープ文字 @bozzmobです。正規表現が操作している文字列にが含まれている場合、出力に違いはありません。正規表現にリテラル$が必要な場合にのみ問題が発生する可能性があります$。特定の問題がある場合、このコメント/回答が役に立たない場合は、別の質問をします。
Ben

51

多分あなたは使用してみることができます

SELECT user_name
FROM user_master
WHERE upper(user_name) LIKE '%ME%'

3
入力パラメータがすべて大文字の場合に機能し、小文字または混合の場合は機能しません
sergionni

13
あなたはWHERE upper(user_name) LIKE UPPER('%ME%')それについて考えましたか?:)
コネラック

3
@sergionniでは、検索語も大文字にする必要があります。
Markus Winand 2011年

3
@sergionni、それでは、なぜUPPER入力パラメーターにも使用しないのですか?
チェコ語2011年

5
@ V4Vendetta upperインデックスを失う関数を使用していますが、インデックスを使用して検索を行う方法はありますか?
jcho360 2013

7

Oracle 12c R2から次のように使用できますCOLLATE operator

COLLATE演算子は、式の照合を決定します。この演算子を使用すると、標準の照合導出ルールを使用して、データベースが式に対して導出した照合をオーバーライドできます。

COLLATE演算子は引数としてcollat​​ion_nameを1つ取り、名前付き照合または疑似照合を指定できます。照合名にスペースが含まれている場合は、名前を二重引用符で囲む必要があります。

デモ:

CREATE TABLE tab1(i INT PRIMARY KEY, name VARCHAR2(100));

INSERT INTO tab1(i, name) VALUES (1, 'John');
INSERT INTO tab1(i, name) VALUES (2, 'Joe');
INSERT INTO tab1(i, name) VALUES (3, 'Billy'); 
--========================================================================--
SELECT /*csv*/ *
FROM tab1
WHERE name = 'jOHN' ;
-- no rows selected

SELECT /*csv*/ *
FROM tab1
WHERE name COLLATE BINARY_CI = 'jOHN' ;
/*
"I","NAME"
1,"John"
*/

SELECT /*csv*/ *
FROM tab1 
WHERE name LIKE 'j%';
-- no rows selected

SELECT /*csv*/ *
FROM tab1 
WHERE name COLLATE BINARY_CI LIKE 'j%';
/*
"I","NAME"
1,"John"
2,"Joe"
*/

db <> fiddleデモ


2
select user_name
from my_table
where nlssort(user_name, 'NLS_SORT = Latin_CI') = nlssort('%AbC%', 'NLS_SORT = Latin_CI')

%2番目の最初の引数でのがNLSSORTされていない権利、ワイルドカードであることを意図しますか?彼らはちょっと混乱しています。
Stefan van den Akker

1

あなたはそのようなことをすることができます:

where regexp_like(name, 'string$', 'i');
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.