NULL值的处理、逻辑操作和函数嵌套
一:什么是NULL
NULL 值是一个很特别的值。它既不是零,也不是空格。它的值是没有定义的、未知的、不确定的。一些英文书中用了如下的词来形容 NULL:“unavailable,unassigned,
undefined,unknown,immeasurable,inapplicable。”总之您没有办法得到它的准确值。
二:含有NULL的表达式的计算
SQL> select ename, sal,comm,sal+comm "Income",job
2 from emp
3 where job not like 'SALES%'
4 order by job;
ENAME SAL COMM Income JOB
---------- ---------- ---------- ---------- ---------
SCOTT 3000 ANALYST
FORD 3000 ANALYST
SMITH 800 CLERK
JAMES 950 CLERK
ADAMS 1100 CLERK
MILLER 1300 CLERK
JONES 2975 MANAGER
BLAKE 2850 MANAGER
CLARK 2450 MANAGER
KING 5000 PRESIDENT
已选择10行。
SQL>
SAL一列全部有值,但是 SAL加上comm之后的Income 一列全部却都是空,问题出在 NULL(空值)上,因为只要在一个表达式中包含任何 NULL(空值),该表达式的值就为 NULL。
SQL> select empno, ename,sal,job,comm from emp where comm is null;
EMPNO ENAME SAL JOB COMM
---------- ---------- ---------- --------- ----------
7369 SMITH 800 CLERK
7566 JONES 2975 MANAGER
7698 BLAKE 2850 MANAGER
7782 CLARK 2450 MANAGER
7788 SCOTT 3000 ANALYST
7839 KING 5000 PRESIDENT
7876 ADAMS 1100 CLERK
7900 JAMES 950 CLERK
7902 FORD 3000 ANALYST
7934 MILLER 1300 CLERK
已选择10行。
SQL> select empno, ename,sal,job,comm from emp where comm is not null;
EMPNO ENAME SAL JOB COMM
---------- ---------- ---------- --------- ----------
7499 ALLEN 1600 SALESMAN 300
7521 WARD 1250 SALESMAN 500
7654 MARTIN 1250 SALESMAN 1400
7844 TURNER 1500 SALESMAN 0
SQL>
三:空值(NULL)的排序
SQL> select empno,job,comm from emp order by comm;
EMPNO JOB COMM
---------- --------- ----------
7844 SALESMAN 0
7499 SALESMAN 300
7521 SALESMAN 500
7654 SALESMAN 1400
7369 CLERK
7566 MANAGER
7900 CLERK
7934 CLERK
7902 ANALYST
7876 CLERK
7698 MANAGER
7782 MANAGER
7788 ANALYST
7839 PRESIDENT
已选择14行。
SQL>
上例表明:在升序排序时,NULL值排在最后。
SQL> select empno,job,comm from emp order by comm desc;
EMPNO JOB COMM
---------- --------- ----------
7369 CLERK
7566 MANAGER
7782 MANAGER
7698 MANAGER
7788 ANALYST
7839 PRESIDENT
7900 CLERK
7934 CLERK
7902 ANALYST
7876 CLERK
7654 SALESMAN 1400
7521 SALESMAN 500
7499 SALESMAN 300
7844 SALESMAN 0
已选择14行。
SQL>
上例表明:在降序排序时,NULL值排在最前。
四:逻辑表达式和逻辑运算符
Oracle提供了AND(逻辑与/逻辑乘)、OR(逻辑加/逻辑或)和NOT(逻辑非)3个逻辑运算符。其中AND(逻辑与/逻辑乘)和OR(逻辑加/逻辑或)把两个条件组合在一起产生一个结果。
其格式如下:
条件1 逻辑运算符 条件2; 它也叫逻辑表达式,这里逻辑运算符为AND或OR。
逻辑表达式有以下的重要特性:
条件1 逻辑运算符 条件2 = 条件2 逻辑运算符 条件1 (定理5.1)
在二值逻辑中逻辑表达式或条件只能为真(T)或假(F)。但在Oracle的逻辑表达式中还引入了另一个值,未知(NULL)。
在二值逻辑中逻辑表达式“条件1AND 条件2”中,只有当条件1和条件2同时为真时其结果才为真,否则为假。但现在我们多了一个NULL值,以上逻辑表达式的结果又该如何呢?
下面是AND的真值表(算法):
F AND F = F F AND T = F F AND NULL = F
T AND F = F T AND T = T T AND NULL IS NULL
NULL AND F = F NULL AND T IS NULL NULL AND NULL IS NULL
您只要能记住真值表的中线和左下角(即黑体)部分就行了。因为剩余部分您可以用定理 5.1 推导出来。您也可以把下划线部分看成对称轴,对称轴上下两部的结果相等。
因此您只要记住对称轴的上部或下部就可以了,另一部分您可以用交换 AND 左右的真值来得到。
AND运算的优先级为:F-->NULL-->T
即在AND逻辑表达式中:
只要有F其结果就为F,如真值表中第一行和第一列所表示的;
如果没有F,在AND逻辑表达式中有NULL其结果就为NULL,如真值表中,除了结果为F的部分最后一行和最后一列所表示的;
只有当两个条件都为T时,AND逻辑表达式的结果才为T,如真值表中正中心所表示的。
SQL> select empno, ename,sal,job
2 from emp
3 where sal >=1500
4 and job in ('SALESMAN','CLERK','MANAGER')
5 order by job;
EMPNO ENAME SAL JOB
---------- ---------- ---------- ---------
7566 JONES 2975 MANAGER
7698 BLAKE 2850 MANAGER
7782 CLARK 2450 MANAGER
7499 ALLEN 1600 SALESMAN
7844 TURNER 1500 SALESMAN
SQL>
下面我们看一下OR的真值表:
T OR T = T T OR F = T T OR NULL = T
F OR T = T F OR F = F F OR NULL IS NULL
NULL OR T = T NULL OR F IS NULL NULL AND NULL IS NULL
同样您只要能记住真值表的中线和左下角(即黑体)部分就行了。因为剩余部分您可以用定理5.1推导出来。您也可以把下划线部分看成对称轴,对称轴上下两部的结果相等。
因此您只要记住对称轴的上部或下部就可以了,另一部分您可以用交换 OR 左右的真值来得到。
OR运算的优先级为: T-->NULL-->F
即在 OR 逻辑表达式中:
只要有 T 其结果就为 T,如真值表中第一行和第一列所表示的;
如果没有T,在 OR 逻辑表达式中有NULL其结果就为NULL,如真值表中,除了结果为T的部分最后一行和最后一列所表示的;
只有当两个条件都为F,OR逻辑表达式的结果才为F,如真值表中正中心所表示的。
SQL> l
1 select empno, ename,sal,job
2 from emp
3 where sal >=1500
4 and job in ('SALESMAN','CLERK','MANAGER')
5* order by job
SQL> 4
4* and job in ('SALESMAN','CLERK','MANAGER')
SQL> c /and/or
4* or job in ('SALESMAN','CLERK','MANAGER')
SQL> l
1 select empno, ename,sal,job
2 from emp
3 where sal >=1500
4 or job in ('SALESMAN','CLERK','MANAGER')
5* order by job
SQL> /
EMPNO ENAME SAL JOB
---------- ---------- ---------- ---------
7788 SCOTT 3000 ANALYST
7902 FORD 3000 ANALYST
7369 SMITH 800 CLERK
7876 ADAMS 1100 CLERK
7934 MILLER 1300 CLERK
7900 JAMES 950 CLERK
7566 JONES 2975 MANAGER
7782 CLARK 2450 MANAGER
7698 BLAKE 2850 MANAGER
7839 KING 5000 PRESIDENT
7499 ALLEN 1600 SALESMAN
7654 MARTIN 1250 SALESMAN
7844 TURNER 1500 SALESMAN
7521 WARD 1250 SALESMAN
已选择14行。
SQL>
现在介绍最后一个逻辑运算符NOT。在二值逻辑中,NOT的真值表非常简单,其真值表如下:
NOT T = F NOT F = T NOT NULL = NULL
五:运算符的优先级
(1)算术运算符→(2)连接运算符→(3)比较(关系)运算符→(4)IS NULL,IS NOT NULL,LIKE,NOT LIKE,IN,NOT IN 运算符→(5)BETWEEN,NOT BETWEEN运算符→(6)NOT逻辑运算符→(7)AND逻辑运算符→(8)OR逻辑运算符。 如果使用了括号,括号中的运算优先。
SQL> select empno, ename,sal,job
2 from emp
3 where job='CLERK'
4 or job='SALESMAN'
5 and sal >= 1300;
EMPNO ENAME SAL JOB
---------- ---------- ---------- ---------
7369 SMITH 800 CLERK
7499 ALLEN 1600 SALESMAN
7844 TURNER 1500 SALESMAN
7876 ADAMS 1100 CLERK
7900 JAMES 950 CLERK
7934 MILLER 1300 CLERK
已选择6行。
SQL>
按照运算符的优先级,Oracle首先执行由黑体部分组成的条件,即首先找到工资在1300元或以上的推销员(SALESMAN);第二步是找到所有的文员(CLERK);最后 Oracle
显示的结果为所有的文员(CLERK)和工资在1300元或以上的推销员(SALESMAN)的信息。
SQL> select empno, ename,job,sal
2 from emp
3 where (job='CLERK' or job='SALESMAN')
4 and sal >= 1300;
EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7499 ALLEN SALESMAN 1600
7844 TURNER SALESMAN 1500
7934 MILLER CLERK 1300
SQL>
按照运算符的优先级,Oracle 首先执行由黑体部分组成的条件,即找出所有的文员(CLERK)和推销员(SALESMAN),接下来找出工资在1300元或以上的员工;
最后Oracle显示的结果为所有工资在1300元或以上的文员(CLERK)和推销员(SALESMAN)的信息。
六:用AND和OR替代BETWEEN AND 和IN运算符
SQL> select empno,ename,sal
2 from emp
3 where sal between 1500 and 2900;
EMPNO ENAME SAL
---------- ---------- ----------
7499 ALLEN 1600
7698 BLAKE 2850
7782 CLARK 2450
7844 TURNER 1500
SQL> select empno,ename,sal
2 from emp
3 where sal >= 1500 and sal <= 2900;
EMPNO ENAME SAL
---------- ---------- ----------
7499 ALLEN 1600
7698 BLAKE 2850
7782 CLARK 2450
7844 TURNER 1500
SQL>
上面两个sql的执行结果是一样的。
SQL> select empno,ename,sal
2 from emp
3 where job in ('SALESMAN','CLERK','MANAGER');
EMPNO ENAME SAL
---------- ---------- ----------
7369 SMITH 800
7499 ALLEN 1600
7521 WARD 1250
7566 JONES 2975
7654 MARTIN 1250
7698 BLAKE 2850
7782 CLARK 2450
7844 TURNER 1500
7876 ADAMS 1100
7900 JAMES 950
7934 MILLER 1300
已选择11行。
SQL> select empno,ename,sal
2 from emp
3 where job='SALESMAN' or job='CLERK' or job='MANAGER';
EMPNO ENAME SAL
---------- ---------- ----------
7369 SMITH 800
7499 ALLEN 1600
7521 WARD 1250
7566 JONES 2975
7654 MARTIN 1250
7698 BLAKE 2850
7782 CLARK 2450
7844 TURNER 1500
7876 ADAMS 1100
7900 JAMES 950
7934 MILLER 1300
已选择11行。
SQL>
上面两个sql的执行结果是一样的。
七:NVL函数
NVL函数是一个空值转换函数。
SQL> L
1 select ename,sal,comm,sal+comm,job
2 from emp
3 where job not like 'SALES%'
4* order by job
SQL> /
ENAME SAL COMM SAL+COMM JOB
---------- ---------- ---------- ---------- ---------
SCOTT 3000 ANALYST
FORD 3000 ANALYST
SMITH 800 CLERK
JAMES 950 CLERK
ADAMS 1100 CLERK
MILLER 1300 CLERK
JONES 2975 MANAGER
BLAKE 2850 MANAGER
CLARK 2450 MANAGER
KING 5000 PRESIDENT
由于表达式sal+comm中comm的值为NULL,我们得到的所有sal+comm都为NULL。Oracle提供的NVL函数可以用来解决这一难题。如下:
SQL> select ename,sal,comm,sal+NVL(comm,0),job
2 from emp
3 where job not like 'SALES%'
4 order by job;
ENAME SAL COMM SAL+NVL(COMM,0) JOB
---------- ---------- ---------- --------------- ---------
SCOTT 3000 3000 ANALYST
FORD 3000 3000 ANALYST
SMITH 800 800 CLERK
JAMES 950 950 CLERK
ADAMS 1100 1100 CLERK
MILLER 1300 1300 CLERK
JONES 2975 2975 MANAGER
BLAKE 2850 2850 MANAGER
CLARK 2450 2450 MANAGER
KING 5000 5000 PRESIDENT
NVL函数是把一空值(NULL)转换成某一实际的值。它的格式如下:
NVL(表达式1,表达式2)
如果表达式1为空值(NULL),NVL返回值为表达式2的值,否则返回表达式1的值。
该函数的目的是把一个空值(NULL)转换成一个实际的值。其表达式 1 和表达式 2可以是数字型、字符型或日期型,但表达式1和表达式2的数据类型必须一致。如:
对数字型:NVL(comm,0);
对字符型:NVL(TO_CHAR(comm),‘No Commission’);
对日期型:NVL(hiredate,‘31-DEC-99’)。
有经验的Oracle开发人员会在他们开发的SQL语句中经常地使用NVL函数以避免因空值(NULL)产生的错误。
八:DECODE函数
因为SQL中没有逻辑判断语句(分支语句),所以Oracle引入了DECODE函数来完成类似的功能。您可以使用下例的查询语句,利用 DECODE 函数求出基于不同职位的(job)每个员工加薪后的工资值。
SQL> l
1 select ename "Name",job,sal "Salary",decode(job,'SALESMAN',sal*1.15,'CLERK',sal*1.2,'ANALYST',sal*1.25,sal*1.4) "New Salary"
2 from emp
3* order by job
SQL> /
Name JOB Salary New Salary
---------- --------- ---------- ----------
SCOTT ANALYST 3000 3750
FORD ANALYST 3000 3750
SMITH CLERK 800 960
ADAMS CLERK 1100 1320
MILLER CLERK 1300 1560
JAMES CLERK 950 1140
JONES MANAGER 2975 4165
CLARK MANAGER 2450 3430
BLAKE MANAGER 2850 3990
KING PRESIDENT 5000 7000
ALLEN SALESMAN 1600 1840
MARTIN SALESMAN 1250 1437.5
TURNER SALESMAN 1500 1725
WARD SALESMAN 1250 1437.5
已选择14行。
SQL>
在上例的查询语句中,DECODE函数执行的步骤如下:
(1)当job为SALESMAN时,DECODE 函数返回表达式sal*1.15的值,否则执行(2)。
(2)当job为CLERK时DECODE函数返回表达式sal*1.2的值,否则执行(3)
(3)当job为ANALYST时DECODE函数返回表达式sal*1.25的值,否则执行(4)
(4)DECODE函数返回表达式sal*1.40的值。
九:单值函数的嵌套
Oracle 的单值函数可以嵌套。函数的计算次序为从里到外。按 Oracle 的说法,Oracle的单值函数可以嵌套任意层。
但这只是在理论上行得通,因为嵌套的层数要受实际可用内存的限制,而实际可用内存又是受操作系统和计算机硬件的限制的。
SQL> select ename "Name",nvl(to_char(comm), ename||' is not a Salesperson') "Commission"
2 from emp
3 order by 2;
Name Commission
---------- ----------------------------------------
TURNER 0
MARTIN 1400
ALLEN 300
WARD 500
ADAMS ADAMS is not a Salesperson
BLAKE BLAKE is not a Salesperson
CLARK CLARK is not a Salesperson
FORD FORD is not a Salesperson
JAMES JAMES is not a Salesperson
JONES JONES is not a Salesperson
KING KING is not a Salesperson
MILLER MILLER is not a Salesperson
SCOTT SCOTT is not a Salesperson
SMITH SMITH is not a Salesperson
在上例的查询语句中,表达式NVL(TO_CHAR(comm), ename||’ is not a Salesperson!’)
的计算次序如下:
(1)Oracle首先用TO_CHAR函数把comm由数字型转换成字符型;
(2)NVL函数测试TO_CHAR(comm);
(3)如果TO_CHAR(comm)不为空就返回TO_CHAR(comm)的值;
(4)如果TO_CHAR(comm)为空就返回表达式ename||’ is not a Salesperson!’的值。
注意:由于 TO_CHAR 函数把 comm 由数字型转换成字符型,因此查询显示的结果是按 ASCII码的顺序排列的。
十:oracle9i新增加的单值函数和表达式
NVL2、NULLIF和COALESCE为Oracle9i新增加的函数,而CASE为Oracle9i新增加的表达式。
NVL2是Oracle9i刚刚引入的一个新函数。NVL2对NVL函数进行了小小的扩充。
SQL> select ename "Name",nvl2(comm,'sal+comm',sal) "Income",job
2 from emp
3 where job not like 'SALES%'
4 order by job;
Name Income JOB
---------- ---------------------------------------- ---------
SCOTT 3000 ANALYST
FORD 3000 ANALYST
SMITH 800 CLERK
JAMES 950 CLERK
ADAMS 1100 CLERK
MILLER 1300 CLERK
JONES 2975 MANAGER
BLAKE 2850 MANAGER
CLARK 2450 MANAGER
KING 5000 PRESIDENT
在上例的查询语句中,表达式NVL2(comm,’sal+comm’,sal)"Income" 的执行次序如下:
(1)NVL2函数测试comm;
(2)如果comm不为空(NULL),就返回表达式sal+comm的值;
(3)如果comm为空(NULL),就返回sal的值;
(4)返回值的列标为Income。
NVL2函数的格式如下:
NVL2(表达式1,表达式2,表达式3)
函数NVL2(表达式1,表达式2,表达式3)的执行次序如下。
如果表达式1不为空值(NULL),NVL2函数返回值为表达式2的值;
如果表达式1为空值(NULL),NVL2函数返回值为表达式3的值。
表达式2和表达式3可以是除LONG以外的任何数据类型,表达式1可以是任何数据类型。
如果表达式2和表达式3的数据类型不同,Oracle服务器把表达式3的数据类型转换成表达式 2的数据类型;此时如果表达式3 为空值,Oracle服务器就不进行数据类型的转换。
NVL2 函数返回值的数据类型与表达式 2 的数据类型相同。但当表达式 2 的数据类型为定长字符型CHAR时,NVL2函数返回值的数据类型为变长字符型VARCHAR2。
NULLIF是Oracle9i新引入的另一函数。您可以使用下例的查询语句来测试这一函数。
SQL> SELECT ename, job, LENGTH(ename) "Name_Length", LENGTH(job) "Job_Lenght",
2 NULLIF(LENGTH(ename),LENGTH(job)) "Comparision"
3 FROM emp;
ENAME JOB Name_Length Job_Lenght Comparision
---------- --------- ----------- ---------- -----------
SMITH CLERK 5 5
ALLEN SALESMAN 5 8 5
WARD SALESMAN 4 8 4
JONES MANAGER 5 7 5
MARTIN SALESMAN 6 8 6
BLAKE MANAGER 5 7 5
CLARK MANAGER 5 7 5
SCOTT ANALYST 5 7 5
KING PRESIDENT 4 9 4
TURNER SALESMAN 6 8 6
ADAMS CLERK 5 5
JAMES CLERK 5 5
FORD ANALYST 4 7 4
MILLER CLERK 6 5 6
从上例可以看出NULLIF函数的功能:
当LENGTH(ename)和LENGTH(job)相等时,函数NULLIF(LENGTH(ename),LENGTH(job))返回空值(NULL);否则返回LENGTH(ename)的值,即ename的长度。
NULLIF函数的格式如下:NULLIF(表达式1,表达式2)
函数NULLIF(表达式1,表达式2)的执行次序如下:
NULLIF函数比较表达式1和表达式2; 如果两个表达式相等就返回空值(NULL); 如果不等就返回表达式1。
NULLIF函数中的表达式1不能为“NULL”。
现在来介绍Oracle9i引入的另一个新函数COALESCE。
SQL> insert into emp(empno,ename) values(10,'testuser');
已创建 1 行。
SQL> select ename,sal,comm,coalesce(comm,sal*0.1,100) "New Commission"
2 from emp;
ENAME SAL COMM New Commission
---------- ---------- ---------- --------------
SMITH 800 80
ALLEN 1600 300 300
WARD 1250 500 500
JONES 2975 297.5
MARTIN 1250 1400 1400
BLAKE 2850 285
CLARK 2450 245
SCOTT 3000 300
KING 5000 500
TURNER 1500 0 0
ADAMS 1100 110
JAMES 950 95
FORD 3000 300
MILLER 1300 130
testuser 100
从上例的结果可以看出COALESCE函数的功能:
当comm 不为空时,COALESCE函数返回comm的值。 如ALLEN的佣金(comm)为300,New Commission的显示也为300;
当 comm 为空,同时 sal*0.1 不为空(即 sae 不为空)时,COALESCE 函数返回sal*0.1的值。如SMITH的佣金(comm)为空,但sal=800不为空,所以COALESCE函数返回800*0.1=80;
当comm 为空并且sal*0.1也为空(即sae为空)时,COALESCE函数返回100。如QUEEN的佣金(comm)为空,并且sal也为空,所以COALESCE函数返回100。
COALESCE函数的格式如下:
COALESCE(表达式1,表达式2,表达式3,…,表达式n)
该函数返回表达式列表(表达式1,表达式2,表达式3,…,表达式n)中第一个不为空的表达式的值。
CASE表达式也是Oracle9i刚刚引入的。它的功能与DECODE函数完全相同,只是它的语法更类似于一般的程序设计语言的 CASE 语句。
SQL> L
1 SELECT ename,job,sal,
2 CASE job WHEN 'SALESMAN' THEN sal*1.15
3 WHEN 'CLERK' THEN sal*1.2
4 WHEN 'ANALYST' THEN sal*1.25
5 ELSE sal*1.4
6 END "New Salary"
7 FROM emp
8* ORDER BY job
SQL> /
ENAME JOB SAL New Salary
---------- --------- ---------- ----------
SCOTT ANALYST 3000 3750
FORD ANALYST 3000 3750
SMITH CLERK 800 960
ADAMS CLERK 1100 1320
MILLER CLERK 1300 1560
JAMES CLERK 950 1140
JONES MANAGER 2975 4165
CLARK MANAGER 2450 3430
BLAKE MANAGER 2850 3990
KING PRESIDENT 5000 7000
ALLEN SALESMAN 1600 1840
MARTIN SALESMAN 1250 1437.5
TURNER SALESMAN 1500 1725
WARD SALESMAN 1250 1437.5
在上例的查询语句中,CASE表达式执行的步骤如下:
当job为SALESMAN时CASE表达式返回表达式sal*1.15的值;
否则,当job为CLERK时CASE表达式返回表达式sal*1.20的值;
否则,当job为ANALYST时CASE表达式返回表达式sal*1.25的值;
否则,CASE表达式返回表达式sal*1.40的值。