ITPub博客

首页 > 数据库 > Oracle > [20250718]关于oracle lnnvl函数.txt

[20250718]关于oracle lnnvl函数.txt

原创 Oracle 作者:lfree 时间:2025-07-18 21:14:34 0 删除 编辑

[20250718]关于oracle lnnvl函数.txt

--//涉及or系列优化,使用or_expand提示,涉及使用oracle lnnvl函数,关于该函数,以前也写过一个简单的例子。
--//简单讲就是结果集合取反,涉及NULL值的特殊情况,全称是 Logical Not Null Value Logic(不知道如何理解)。
--//通过一些简单的例子再次说明,并且加强记忆。

1.环境:
SCOTT@book01p> @ver2
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 21.0.0.0.0
BANNER                        : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY                 : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID                        : 0
PL/SQL procedure successfully completed.

2.测试:
SCOTT@book01p> select * from emp where comm >=500;
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30
      7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30

--//如果使用lnnvl(comm >=500),相当于整个集合取反,如果使用comm <500是不行(因为NULL值的存在):
SCOTT@book01p> select * from emp where comm <500;
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30
      7844 TURNER     SALESMAN        7698 1981-09-08 00:00:00       1500          0         30
--//可以发现不包含空值的情况,使用lnnvl(comm >=500)就没有问题,类似集合的取反。

SCOTT@book01p> set null null
SCOTT@book01p> select * from emp where lnnvl(comm >=500);
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800 null               20
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30
      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975 null               20
      7698 BLAKE      MANAGER         7839 1981-05-01 00:00:00       2850 null               30
      7782 CLARK      MANAGER         7839 1981-06-09 00:00:00       2450 null               10
      7788 SCOTT      ANALYST         7566 1987-07-13 00:00:00       3000 null               20
      7839 KING       PRESIDENT null       1981-11-17 00:00:00       5000 null               10
      7844 TURNER     SALESMAN        7698 1981-09-08 00:00:00       1500          0         30
      7876 ADAMS      CLERK           7788 1987-07-13 00:00:00       1100 null               20
      7900 JAMES      CLERK           7698 1981-12-03 00:00:00        950 null               30
      7902 FORD       ANALYST         7566 1981-12-03 00:00:00       3000 null               20
      7934 MILLER     CLERK           7782 1982-01-23 00:00:00       1300 null               10
12 rows selected.
--//简单理解就是排除comm >=500的情况的结果集,也可以写成如下:
--//select * from emp where comm <500 or comm is null;
--//输出略。

--//如果查询范围写成如下:
SCOTT@book01p> select * from emp where comm >=500 and comm <=1000;
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30

--//如果要取反,写成如下会报错。
SCOTT@book01p> select * from emp where lnnvl(comm >=500 and comm <=1000);
select * from emp where lnnvl(comm >=500 and comm <=1000)
                                         *
ERROR at line 1:
ORA-00907: missing right parenthesis

SCOTT@book01p> select * from emp where lnnvl(comm between 500 and 1000);
select * from emp where lnnvl(comm between 500 and 1000)
*
ERROR at line 1:
ORA-13207: incorrect use of the [LNNVL] operator
--//oracle不支持里面表达式存在and,or操作。

--//要支持这种情况的取反,写成如下,注意要使用or条件。
SCOTT@book01p> select * from emp where lnnvl(comm >=500) or lnnvl(comm <=1000);
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800 null               20
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30
      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975 null               20
      7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30
      7698 BLAKE      MANAGER         7839 1981-05-01 00:00:00       2850 null               30
      7782 CLARK      MANAGER         7839 1981-06-09 00:00:00       2450 null               10
      7788 SCOTT      ANALYST         7566 1987-07-13 00:00:00       3000 null               20
      7839 KING       PRESIDENT null       1981-11-17 00:00:00       5000 null               10
      7844 TURNER     SALESMAN        7698 1981-09-08 00:00:00       1500          0         30
      7876 ADAMS      CLERK           7788 1987-07-13 00:00:00       1100 null               20
      7900 JAMES      CLERK           7698 1981-12-03 00:00:00        950 null               30
      7902 FORD       ANALYST         7566 1981-12-03 00:00:00       3000 null               20
      7934 MILLER     CLERK           7782 1982-01-23 00:00:00       1300 null               10
13 rows selected.

--//或者写成如下:
SCOTT@book01p> select * from emp where comm <500 or comm >1000 or comm is null;
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800 null               20
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30
      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975 null               20
      7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30
      7698 BLAKE      MANAGER         7839 1981-05-01 00:00:00       2850 null               30
      7782 CLARK      MANAGER         7839 1981-06-09 00:00:00       2450 null               10
      7788 SCOTT      ANALYST         7566 1987-07-13 00:00:00       3000 null               20
      7839 KING       PRESIDENT null       1981-11-17 00:00:00       5000 null               10
      7844 TURNER     SALESMAN        7698 1981-09-08 00:00:00       1500          0         30
      7876 ADAMS      CLERK           7788 1987-07-13 00:00:00       1100 null               20
      7900 JAMES      CLERK           7698 1981-12-03 00:00:00        950 null               30
      7902 FORD       ANALYST         7566 1981-12-03 00:00:00       3000 null               20
      7934 MILLER     CLERK           7782 1982-01-23 00:00:00       1300 null               10
13 rows selected.

4.关于lvnvl函数的返回值,这个问题实际上一直困惑我。

SCOTT@book01p> select dept.*,lnnvl(deptno = 10) from dept where LNNVL(DEPTNO = 10);
    DEPTNO DNAME                          LOC           LNNVL(DEPTNO = 10)
---------- ------------------------------ ------------- ----------------
        20 RESEARCH                       DALLAS        null
        30 SALES                          CHICAGO       null
        40 OPERATIONS                     BOSTON        null

SCOTT@book01p> select dept.*,lnnvl(deptno = 10) from dept ;
    DEPTNO DNAME                          LOC           LNNVL(DEPTNO = 10)
---------- ------------------------------ ------------- ----------------
        10 ACCOUNTING                     NEW YORK      null
        20 RESEARCH                       DALLAS        null
        30 SALES                          CHICAGO       null
        40 OPERATIONS                     BOSTON        null

--//当deptno = 10时,LNNVL(DEPTNO = 10)返回是NULL值,其他情况也是null,oracle不知道如何判断真假。
--//不是通过返回值判断的吗?

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-3091652/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
熟悉oracle相关技术,擅长sql优化,rman备份与恢复,熟悉linux shell编程。

注册时间:2008-01-03

  • 博文量
    4006
  • 访问量
    7969294