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

相关推荐
fen_fen14 小时前
Oracle建表语句示例
数据库·oracle
此刻你18 小时前
常用的 SQL 语句
数据库·sql·oracle
海心焱1 天前
从零开始构建 AI 插件生态:深挖 MCP 如何打破 LLM 与本地数据的连接壁垒
jvm·人工智能·oracle
德彪稳坐倒骑驴1 天前
MySQL Oracle面试题
数据库·mysql·oracle
吕司1 天前
MySQL库的操作
数据库·mysql·oracle
dishugj1 天前
【Oracle】 rac的一些问题以及解决方案
数据库·oracle
eWidget1 天前
面向信创环境的Oracle兼容型数据库解决方案
数据库·oracle·kingbase·数据库平替用金仓·金仓数据库
熊文豪1 天前
关系数据库替换用金仓——Oracle兼容性深度解析
数据库·oracle·金仓数据库·电科金仓·kes
eWidget1 天前
面向Oracle生态的国产高兼容数据库解决方案
数据库·oracle·kingbase·数据库平替用金仓·金仓数据库
A懿轩A1 天前
【MySQL 数据库】MySQL 数据库核心概念详解:库、表、字段、主键与关系型模型一文读懂
数据库·mysql·oracle