Based on the SQLD exam syllabusReport an error
NVL(a, b) returns b if a is NULL. NVL2(a, b, c) returns b if a is NOT NULL, and c if it is NULL.NULLIF(a, b) returns NULL if the two values are equal, otherwise a. COALESCE returns the first non-NULL argument.CASE column WHEN NULL cannot catch NULL. DECODE treats NULLs as equal to each other.'' as NULL.So far we've seen that NULL turns arithmetic into NULL. Today's functions turn NULL into another value, or conversely turn a value into NULL.
| Function | Result | Example → Result |
|---|---|---|
NVL(a, b) | b if a is NULL, otherwise a | NVL(NULL, 0) → 0 |
NVL2(a, b, c) | b if a is not NULL, c if NULL | NVL2(300, 'Y', 'N') → Y |
NULLIF(a, b) | NULL if a = b, otherwise a | NULLIF(10, 10) → NULL |
COALESCE(a, b, c, …) | The first non-NULL value | COALESCE(NULL, NULL, 3) → 3 |
ISNULL(a, b) | SQL Server's NVL | Does not exist in Oracle |
SELECT ENAME, COMM, NVL(COMM, 0) C0, SAL + COMM S1, SAL + NVL(COMM, 0) S2 FROM EMP WHERE DEPTNO = 30;ENAME COMM C0 S1 S2
---------- ---------- ---------- ---------- ----------
ALLEN 300 300 1900 1900
WARD 500 500 1750 1750
MARTIN 1400 1400 2650 2650
BLAKE 0 2850
TURNER 0 0 1500 1500
JAMES 0 950SAL + COMM is NULL, but SAL + NVL(COMM, 0) gives the salary as is.The types of the two arguments must match. If you give a string as the replacement for the numeric column COMM, Oracle tries to convert 'NONE' to a number and fails.
SELECT ENAME, NVL(COMM, 'NONE') FROM EMP WHERE DEPTNO = 10;SELECT ENAME, NVL(COMM, 'NONE') FROM EMP WHERE DEPTNO = 10
*
ERROR at line 1:
ORA-01722: unable to convert string value containing 'N' to a number:
ORA-03302: (ORA-01722 details) invalid string value: NONENVL(TO_CHAR(COMM), 'NONE').ISNULL(COMM, 0). In Oracle, ISNULL is an ORA-00904 (invalid identifier) error.SELECT ENAME, COMM, NVL2(COMM, 'Has comm', 'No comm') FLAG, NVL2(COMM, SAL + COMM, SAL) PAY FROM EMP WHERE DEPTNO = 30;ENAME COMM FLAG PAY
---------- ---------- ------------ ----------
ALLEN 300 Has comm 1900
WARD 500 Has comm 1750
MARTIN 1400 Has comm 2650
BLAKE No comm 2850
TURNER 0 Has comm 1500
JAMES No comm 950Has comm.SELECT ENAME, SAL, NULLIF(SAL, 1250) N FROM EMP WHERE DEPTNO = 30;ENAME SAL N
---------- ---------- ----------
ALLEN 1600 1600
WARD 1250
MARTIN 1250
BLAKE 2850 2850
TURNER 1500 1500
JAMES 950 950NULLIF(a, b) is the same as CASE WHEN a = b THEN NULL ELSE a END. To prevent division by zero, it is used like x / NULLIF(y, 0).SELECT ENAME, COMM, MGR, COALESCE(COMM, MGR, 0) C FROM EMP WHERE DEPTNO IN (10, 30);ENAME COMM MGR C
---------- ---------- ---------- ----------
ALLEN 300 7698 300
WARD 500 7698 500
MARTIN 1400 7698 1400
BLAKE 7839 7839
CLARK 7839 7839
KING 0
TURNER 0 7698 0
JAMES 7698 7698
MILLER 7782 7782NVL. The difference is that it can take three or more. If all arguments are NULL, the result is NULL too.This is Week 4 material, but it pairs with the NULL functions, so let's look at just the results first.
SELECT COUNT(COMM) A, COUNT(NVL(COMM, 0)) B, SUM(COMM) C, AVG(COMM) D, AVG(NVL(COMM, 0)) E FROM EMP; A B C D E
---------- ---------- ---------- ---------- ----------
4 14 2200 550 157.142857AVG(COMM) divides by the 4 employees who have a COMM (2200 / 4). To get the average over all 14, you have to fill in 0 with NVL (2200 / 14).CASE comes in two forms.
| Form | Syntax | Comparison method |
|---|---|---|
| simple CASE | CASE expr WHEN value THEN result … [ELSE result] END | expr = value (equality only) |
| searched CASE | CASE WHEN condition THEN result … [ELSE result] END | Any condition (>, BETWEEN, IS NULL …) |
SELECT ENAME, DEPTNO, CASE DEPTNO WHEN 10 THEN 'ACCOUNTING' WHEN 20 THEN 'RESEARCH' ELSE 'ETC' END DNAME FROM EMP WHERE JOB = 'MANAGER';ENAME DEPTNO DNAME
---------- ---------- ----------
JONES 20 RESEARCH
BLAKE 30 ETC
CLARK 10 ACCOUNTINGRange conditions are written with a searched CASE.
SELECT ENAME, SAL, CASE WHEN SAL >= 3000 THEN 'HIGH' WHEN SAL >= 1500 THEN 'MID' ELSE 'LOW' END GRADE FROM EMP WHERE DEPTNO = 20;ENAME SAL GRAD
---------- ---------- ----
SMITH 800 LOW
JONES 2975 MID
SCOTT 3000 HIGH
ADAMS 1100 LOW
FORD 3000 HIGH⚠️ The order of WHEN changes the result. CASE stops at the first WHEN that is true. If you write the broad condition (
>= 1500) first, as below, even SAL 3000 gets caught there, and not a singleHIGHappears.
SELECT ENAME, SAL, CASE WHEN SAL >= 1500 THEN 'MID' WHEN SAL >= 3000 THEN 'HIGH' ELSE 'LOW' END GRADE FROM EMP WHERE DEPTNO = 20;ENAME SAL GRAD
---------- ---------- ----
SMITH 800 LOW
JONES 2975 MID
SCOTT 3000 MID
ADAMS 1100 LOW
FORD 3000 MIDELSE is left out, rows that match none of the WHENs get NULL.SELECT ENAME, SAL, CASE WHEN SAL > 2000 THEN SAL * 1.1 END RAISE FROM EMP WHERE DEPTNO = 10;ENAME SAL RAISE
---------- ---------- ----------
CLARK 2450 2695
KING 5000 5500
MILLER 1300The results of THEN and ELSE must be of the same type. If the first result is a string, the rest must be strings too.
SELECT CASE 1 WHEN 1 THEN 'A' WHEN 2 THEN 2 END FROM DUAL;SELECT CASE 1 WHEN 1 THEN 'A' WHEN 2 THEN 2 END FROM DUAL
*
ERROR at line 1:
ORA-00932: expression (2) is of data type NUMBER, which is incompatible with expected data type CHARDECODE(expr, value1, result1, value2, result2, …, default) is a simple CASE written as a single function.
SELECT ENAME, DEPTNO, DECODE(DEPTNO, 10, 'ACCOUNTING', 20, 'RESEARCH', 'ETC') DNAME FROM EMP WHERE JOB = 'MANAGER';ENAME DEPTNO DNAME
---------- ---------- ----------
JONES 20 RESEARCH
BLAKE 30 ETC
CLARK 10 ACCOUNTING'ETC' above, BLAKE becomes NULL.SAL >= 3000 can't be used directly in DECODE, so use a searched CASE.SELECT ENAME, COMM, DECODE(COMM, NULL, 'Is NULL', 'Has value') D, CASE COMM WHEN NULL THEN 'Is NULL' ELSE 'Has value' END C FROM EMP WHERE DEPTNO = 30;ENAME COMM D C
---------- ---------- --------- ---------
ALLEN 300 Has value Has value
WARD 500 Has value Has value
MARTIN 1400 Has value Has value
BLAKE Is NULL Has value
TURNER 0 Has value Has value
JAMES Is NULL Has valueCOMM = NULL. A = with NULL is never true, so BLAKE and JAMES also fall through to Has value.DECODE treats NULL and NULL as equal. That's why it picks out NULL correctly.CASE WHEN COMM IS NULL THEN ….⚠️ In Oracle,
''is NULL. There is no separate zero-length string. So'' IS NULLis true andNVL('', 'EMPTY')isEMPTY. SQL Server treats''and NULL as different values.
SELECT CASE WHEN '' IS NULL THEN 'NULL' ELSE 'NOT NULL' END E, NVL('', 'EMPTY') N FROM DUAL;E N
-------- -----
NULL EMPTY| Comparison | Oracle | SQL Server |
|---|---|---|
What '' is | NULL | Zero-length string |
| NULL replacement functions | NVL, COALESCE | ISNULL, COALESCE |
| Conditional branching | CASE, DECODE | CASE |
Tomorrow covers the comparison and logical operators that pick rows in the WHERE clause, and the pitfalls of conditions involving NULL.
Click a choice to reveal the answer and explanation.
Question 1
In the EMP table, BLAKE's SAL is 2850 and COMM is NULL. Which is the correct result of the following SQL? ```sql SELECT NVL2(COMM, SAL + COMM, SAL) FROM EMP WHERE ENAME = 'BLAKE'; ```
Question 2
Which is the correct result of the following SQL? ```sql SELECT COALESCE(NULL, NULLIF(5, 5), 7, 9) FROM DUAL; ```
Question 3
For an employee whose SAL is 3000, which is the correct result of the following CASE expression? ```sql SELECT CASE WHEN SAL >= 1500 THEN 'MID' WHEN SAL >= 3000 THEN 'HIGH' ELSE 'LOW' END FROM EMP WHERE ENAME = 'SCOTT'; ```
Question 4
In Oracle, which is the correct result of the following SQL? ```sql SELECT NVL('', 'EMPTY') FROM DUAL; ```
Question 5
For a row whose DEPTNO is 30, which is the correct result of the following expression? ```sql SELECT DECODE(DEPTNO, 10, 'A', 20, 'B') FROM EMP WHERE ENAME = 'BLAKE'; ```