|
他のテーブルにデータが存在するかどうかをチェックする。
複数の値のうち、いずれかの値に合致した場合に真になる。
select * from EMP where MGR in(0, 7698); ↓↑等価 select * from EMP where (MGR=0 or MGR=7698);
「in」の後に丸括弧で囲んでカンマ区切りで複数の値を記述する。
確か、1000個を超えるとエラーになる。
値が1個しかない場合は括弧を省略することが出来る。(意味があるのかどうかは知らない(苦笑))
select * from EMP where MGR in 7698;
副問合せで取得した値をin句に指定することが出来る。[2010-12-29]
select * from DEPT where DEPTNO in (select DEPTNO from EMP);
ただ、inよりexistsを使った方が速いらしい。
(DEPTとEMPくらいじゃ件数が少ないから違いは出ないが、結合方法が異なるらしい。
inの方は副問合せの全件検索が入るから遅い? であれば、副問合せの件数が少なければinが速くても不思議は無いような)
select * from DEPT d where exists(select * from EMP e where e.DEPTNO = d.DEPTNO);
なお、inはexistsに置き換えられるが、not inはnot
existsに置き換えられるとは限らないそうだ(データにNULLがある場合の挙動が異なる)。
参考: ミックさんの3値論理とNULL 3.NOT INとNOT EXISTSは同値ではない(3値論理)
副問合せで取得した値と等しいかどうかを条件に指定することが出来る。[2010-12-29]
(「=」だけでなく、他の演算子も使える)
-- 'A'で始まるDNAMEのDEPTNOを取得し、その値を持つEMPを検索する select EMPNO, DEPTNO from EMP where DEPTNO = (select DEPTNO from DEPT where DNAME like'A%');
このとき、副問合せの取得結果は1レコードでなければならない。実行時に複数レコード取れるとエラーが発生する。
SQL> select EMPNO, DEPTNO from EMP
2 where DEPTNO = (select DEPTNO from DEPT where DNAME like'A%' or DNAME like'R%');
where DEPTNO = (select DEPTNO from DEPT where DNAME like'A%' or DNAME like'R%')
*
行2でエラーが発生しました。:
ORA-01427: 単一行副問合せにより2つ以上の行が戻されます
この場合、inで置き換えるというのが常套手段だが、anyを付けるという手もある。
select EMPNO, DEPTNO from EMP where DEPTNO in (select DEPTNO from DEPT where DNAME like'A%' or DNAME like'R%');
select EMPNO, DEPTNO from EMP where DEPTNO = any(select DEPTNO from DEPT where DNAME like'A%' or DNAME like'R%');
like検索では、「%」が0文字以上のマッチング、「_」が1文字のマッチング。[2007-08-12]
ちなみにMS-Accessでは「*」と「?」。
Oracleでは全角文字の「%」「_」も半角文字の「%」「_」と同様の働きをする。
「%」や「_」の文字そのものを検索条件に含めたいときは、escapeという文法を使用してエスケープ文字を指定する。
SQL> select ENAME from EMP 2 where ENAME like'S\%H' escape '\';
なお、like用のエスケープ文字の指定はSQL*Plusのシステム変数のescapeとは無関係。
(escape文に指定する文字には影響するみたいだけど)
WHERE句に複数の条件を記述していくが、そこに書かれている順番と実際に判定される順番は、一致するとは限らない。[2010-07-24]
ルールベースでは、INDEXの無い項目を条件にしている場合、WHEREに書かれた条件の順番に意味が出てくるらしい。
また、ANDとORでは判定される順番が異なるらしい。
ORDERED_PREDICATESヒントで、WHERE条件の評価順序を固定するらしい。