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的判断,再比较吧。

相关推荐
Albert Tan6 小时前
Oracle EBS 缺少adcfgclone.pl文件
数据库·oracle
典孝赢麻崩乐急1 天前
数据库学习--------数据库日志类型及其与事务特性的关系
数据库·oracle
赵渝强老师1 天前
【赵渝强老师】OceanBase租户的资源管理
数据库·mysql·oracle·oceanbase
帧栈1 天前
开发避坑短篇(12):达梦数据库TIMESTAMP字段日期区间查询实现方案
数据库·sql·oracle
ALLSectorSorft2 天前
相亲小程序聊天与互动系统模块搭建
java·数据库·sql·microsoft·oracle
Python大数据分析@2 天前
SQL 怎么学?
数据库·sql·oracle
数据狐(DataFox)2 天前
大数据集分页优化:LIMIT OFFSET的替代方案
数据库·sql·oracle
胖头鱼的鱼缸(尹海文)2 天前
数据库管理-第352期 从需求看懂Oracle RAC多租户环境的Service(20250729)
数据库·oracle
会掉头发2 天前
PostgreSQL缓冲区管理器
数据库·oracle
bestsun9993 天前
Time drifts can result in unexpected behavior such as time-outs.
数据库·oracle