5 NULL值的处理、逻辑操作和函数嵌套

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的值。

 

你可能感兴趣的:(5 NULL值的处理、逻辑操作和函数嵌套)