SYS_OP_MAP_NONNULL NULL的等值比较

无意在数据库中发现了这个操作SYS_OP_MAP_NONNULL。

SYS_OP_MAP_NONNULL应该不是数据库中的对象,因为在DBA_OBJECTS中根本找不到它,而在STANDARD和DBMS_STANDARD包中也找不到函数说明。

SQL> SELECT *
2 FROM DBA_OBJECTS
3 WHERE OBJECT_NAME = 'SYS_OP_MAP_NONNULL';

未选定行

SQL> SELECT *
2 FROM DBA_SOURCE
3 WHERE UPPER(TEXT) LIKE '%SYS_OP_MAP_NONNULL%';

未选定行

SYS_OP_MAP_NONNULL又可以跟参数,它不符合伪列的特性,因此暂且认为这是一个操作。不过文档中并没有这个操作的任何相关记录。

其实这个操作实现的就是DUMP函数的功能:

SQL> SELECT SYS_OP_MAP_NONNULL(5) FROM DUAL;

SYS_OP

C10600

SQL> SELECT SYS_OP_MAP_NONNULL('A') FROM DUAL;

SYS_

4100

SQL> SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'), SYS_OP_MAP_NONNULL(SYSDATE) FROM DUAL;

TO_CHAR(SYSDATE,'YY SYS_OP_MAP_NONNU


2010-08-06 02:19:47 786E080603143000

SQL> SELECT SYS_OP_MAP_NONNULL(NULL) FROM DUAL;

SY

FF

和DUMP的区别在于NULL的处理上,DUMP的参数如果是NULL,返回结果也是NULL,而SYS_OP_MAP_NONNULL返回的是FF,而这正是NULL存储在数据块中的编码。

SQL> SELECT DUMP(NULL) FROM DUAL;

DUMP

NULL

可以认为SYS_OP_MAP_NONNULL返回的就是这个数据类型存储的编码:

SQL> CREATE TABLE T_TEST
2 (ID NUMBER,
3 C1 LONG,
4 C2 CLOB);

表已创建。

SQL> INSERT INTO T_TEST
2 VALUES (1, 'ABC', 'DEF');

已创建 1 行。

SQL> SELECT DUMP(C1) FROM T_TEST;
SELECT DUMP(C1) FROM T_TEST
*
第 1 行出现错误:
ORA-00997: 非法使用 LONG 数据类型

SQL> SELECT DUMP(C2) FROM T_TEST;
SELECT DUMP(C2) FROM T_TEST
*
第 1 行出现错误:
ORA-00932: 数据类型不一致: 应为 -, 但却获得 CLOB

SQL> SELECT SYS_OP_MAP_NONNULL(C1) FROM T_TEST;

SYS_OP_MAP_NONNULL(C1)

01000186000000D104000000820100012A9013002A90130008003F00E83F000000000000000000000000D7D103003200030000000000000060000000909500D1030100000000000000000000000000000000000000000000000000000000000000000000080000005496D7D10301000004002A009E0900004400C0006C0E150

SQL> SELECT SYS_OP_MAP_NONNULL(C2) FROM T_TEST;

SYS_OP_MAP_NONNULL(C2)

006A0001020C8800000200000001000000AB8D630013902B0013902A000300030354000100440045004600000000000000000000D1D7965701030004002A0000099E00C000440E6C150000000013902A0100018600000016090000000000000600000000000100440045004600

二者还有一个很重要的区别就是DUMP不支持LONG以及大对象,而SYS_OP_MAP_NONNULL则支持任意的数据类型。

利用Oracle的这个功能,可以更方便的检查数据的存储格式。

---------------null比较

Oracle的Null真是个麻烦的东西。

不能与其他变量进行比较,甚至不能和NULL进行比较。

仅仅能用IS (NOT) NULL。

来看这个实验,看看能不能知道执行的结果。

先准备数据:

执行一个查询,来猜猜结果

执行结果如下,是你的预期吗?

从结果来看,两行null被合并了。

问题来了,知道null和null是绝对不相等的,为什么会合并掉呢?

经查证,这里ORACLE内部用了个未公开的函数sys_op_map_nonnull

我们来测试一下这个函数

对于NULL

对于非NULL

我们看sys_op_map_nonnull(null)=FF,而FF这正是NULL存储在数据块中的编码。

利用该函数对两个NULL进行比较。

但是不要走火入魔,这种非公开函数不要在项目中使用,因为Oracle不会对它出现的问题负责哦。

项目中如果需要对可为NULL的变量进行比较操作,还是老老实实前面加是否为NULL的判断,再比较吧。

相关推荐
jnrjian7 小时前
expdp file 带时间戳 date
oracle
六月雨滴8 小时前
存储性能监控与优化及最佳实践总结
数据库·oracle·dba
学习论之费曼学习法8 小时前
Agent记忆系统:让AI拥有长期记忆能力
数据库·人工智能·oracle
arronKler10 小时前
数据库设计三大范式
数据库·oracle
oradh11 小时前
Oracle物理存储结构概述
数据库·oracle·物理结构·oracle基础·oracle入门·oracle物理存储结构概述
数据最前线12 小时前
亡羊补牢?Oracle 计划推出月度安全补丁
数据库·oracle
这个DBA有点耶13 小时前
某银行核心系统从Oracle迁移到国产数据库全程复盘(DBA视角)
数据库·经验分享·sql·oracle·dba·智能硬件
阿坤带你走近大数据14 小时前
DM达梦数据库的介绍
数据库·mysql·oracle·国产信创
我科绝伦(Huanhuan Zhou)14 小时前
oracle linux8.8一键部署oracle 11g
数据库·oracle
数据库小学妹14 小时前
企业级数据库迁移实践:从Oracle到国产数据库的兼容性与实施策略
数据库·mysql·oracle·dba