汎用関数の問題
変換関数という言い方はしないけれど、「値がNULLだったら、指定した値に変えて出力する」という関数NVLがあります。Oracleにのみ、古いバージョンから提供されていて、Oracleの開発者の間では有名な関数の1つです。一方、Oracleユーザーになじみが薄い(?)と思われるNULLIFやCOALESCEという関数がありますが、これらはANSI/規格の関数です。使いこなせるのはNVLだけでは困ります。
問2
次を確認してください。
SQL> SELECT empno,comm,sal FROM emp;
EMPNO COMM SAL
---------- ---------- ----------
7369 800
7499 300 1600
7521 500 1250
7566 2975
7654 1400 1250
7698 2850
7782 2450
7839 5000
7844 0 1500
7900 950
7902 3000
7934 1300
COMM列の値がNULLであれば、SAL列の10%を返すSQLをすべて選びなさい。
- a. SELECT empno,NVL(comm,sal*0.1) AS comm FROM emp;
- b. SELECT empno,NVL2(comm,comm,sal*0.1) AS comm FROM emp;
- c. SELECT empno,NVL2(NULLIF(sal,NVL(comm,sal)),comm,sal*0.1) AS comm FROM emp;
正解は、選択肢a、b、cです(全選択肢が正解という設問は、実際の試験にはありません)。
設問の関数は次のとおりです。
| 関数 | 説明 |
|---|---|
| NVL(列値) | 列値がNULLならば値を返す |
| NVL2(列値, 値1, 値2) | 列値がNULLならば値2を返し、NULL以外であれば値1を返す |
| NULLIF(列1, 列2) | 列1と列2が等価ならばNULLを返し、非等価ならば列1の値を返す |
実行結果は次のとおりです。
SQL> --選択肢a
SQL> SELECT empno,NVL(comm,sal*0.1) AS comm FROM emp;
EMPNO COMM
---------- ----------
7369 80
7499 300
7521 500
7566 297.5
7654 1400
7698 285
7782 245
7839 500
7844 0
7900 95
7902 300
7934 130
SQL> --選択肢b
SQL> SELECT empno,NVL2(comm,comm,sal*0.1) AS comm FROM emp;
EMPNO COMM
---------- ----------
7369 80
7499 300
7521 500
7566 297.5
7654 1400
7698 285
7782 245
7839 500
7844 0
7900 95
7902 300
7934 130
SQL> --選択肢c
SQL> SELECT empno,NVL2(NULLIF(sal,NVL(comm,sal)),comm,sal*0.1) AS comm FROM emp;
EMPNO COMM
---------- ----------
7369 80
7499 300
7521 500
7566 297.5
7654 1400
7698 285
7782 245
7839 500
7844 0
7900 95
7902 300
7934 130
選択肢cは、頭の中で関数の実行結果をトレース(処理の過程を頭の中で追いかけていくこと)できないと、正解か否か判断できません。
「そんな無理やり使わなくても」と思ったでしょうが、試験では、入れ子になった関数がいろんなところ(結合や副問合せDMLなど)で登場します。結合について理解できていても、入れ子になった関数の結果を追い間違えて(トレースできなくて)正解の選択肢を見つけられなかったということがあり得ます。入れ子になった関数は面倒くさがらず落ち着いてトレースしてください。
試験会場では、ペンとメモ用紙みたいなものを渡してくれるので、入れ子の内側の結果から順に、メモしていけば良いでしょう。

