Oracle SQLでIN句に引数(パラメータ)を渡す方法
OracleのSQLでIN句に引数(パラメータ)を渡す方法です。
PL/SQL の動的 SQL を使ってプログラミングすれば可能ですが、いちいちプログラムを書かかずに SELECT 文で確認したいときもあるものです。
やり方としては、カンマ区切り文字列を引数として用意し、それを分割して SELECT 文の IN 句に渡します。
ここでは OracleのSQLでIN句に引数(パラメータ)を渡す方法 をサンプル付きで解説します。
環境
- Oracle 11g
ここでは Oracle 11g ですが、10g 以上であれば何でも構いません。
例題で使うテーブルとデータです。
CREATE TABLE EMPLOYEES (
ID NVARCHAR2(255) NOT NULL,
NAME NVARCHAR2(255) NOT NULL,
EMAIL NVARCHAR2(255),
SEX NVARCHAR2(1),
SALARY NUMBER,
CREATED_AT DATE NOT NULL,
UPDATED_AT DATE,
CONSTRAINT PK_EMPLOYEES PRIMARY KEY (ID) USING INDEX
);
INSERT INTO EMPLOYEES VALUES('001','hoge','hoge@example.com','1','30',sysdate,sysdate);
INSERT INTO EMPLOYEES VALUES('002','piyo','piyo@example.com','2','50',sysdate,sysdate);
INSERT INTO EMPLOYEES VALUES('003','fuga','fuga@example.com',null,null,sysdate,sysdate);
INSERT INTO EMPLOYEES VALUES('004','foo','foo@example.com','2','65',sysdate,sysdate);
INSERT INTO EMPLOYEES VALUES('005','bar','bar@example.com','1','25',sysdate,sysdate);
INSERT INTO EMPLOYEES VALUES('006','baz','baz@example.com','2','70',sysdate,sysdate);
INSERT INTO EMPLOYEES VALUES('007','saka','saka@example.com',null,'1000',sysdate,sysdate);
SELECT文のIN句に引数を渡す方法
まず NAME カラムが下記のものを出力することとしましょう。
'hoge,foo,baz'
当然、下記の SELECT 文では、結果は得られません。
SELECT * FROM EMPLOYEES
WHERE NAME IN ('hoge,foo,baz');
ただの文字列ですからね、期待する結果が得られないのは当然です。
なので、カンマで区切った文字列を、個々の文字列に分割し、それを IN 句に渡すことにします。
Oracle では REGEXP_SUBSTR
(DB >=10g) という関数が用意されています。REGEXP_SUBSTR
関数は、正規表現パターンで文字列を検索できるように SUBSTR
の機能を拡張したもので、これを使えば簡単に実現できます。
まず、このカンマ区切りの文字列を分割し、個々の文字列を行として与えるためのクエリを作成します。
SELECT REGEXP_SUBSTR('hoge,foo,baz', '[^,]+', 1, LEVEL) FROM DUAL
CONNECT BY REGEXP_SUBSTR('hoge,foo,baz', '[^,]+', 1, LEVEL) IS NOT NULL
REGEXP_SUBSTR を使う場合には CONNECT BY 句が必要になります。
このクエリは対象文字列からカンマを検索し、文字列として分割します。区切り文字が見つかった場合は、対象文字列を行として返してくれます。
これを SELECT 文に渡してやれば、目的の結果が得られます。
SELECT * FROM EMPLOYEES
WHERE NAME IN (
SELECT REGEXP_SUBSTR('hoge,foo,baz', '[^,]+', 1, LEVEL) FROM DUAL
CONNECT BY REGEXP_SUBSTR('hoge,foo,baz', '[^,]+', 1, LEVEL) IS NOT NULL
)
実行してみると・・・、
おおお、やりましたーー^^
こんな感じでバインド変数でも対応できますよ。
SELECT * FROM EMPLOYEES
WHERE NAME IN (
SELECT REGEXP_SUBSTR(:names, '[^,]+', 1, LEVEL) FROM DUAL
CONNECT BY REGEXP_SUBSTR(:names, '[^,]+', 1, LEVEL) IS NOT NULL
)
参考サイト
まとめ
OracleのSQLでIN句に引数(パラメータ)を渡す方法を紹介しました。
この方法は PL/SQL の CURSOR 文でも利用できます。動的 SQL を書くのが面倒だったらこの方法を利用してみてください。
ちょっと SQL 文が長くなるのが玉に瑕ですが、まぁ仕方ないかな。使い方を忘れたらこのサイトを思い出して見に来てください。
おつかれさまでした。