您好,欢迎访问一九零五行业门户网

Oracle的NULL代表的含义是不确定,那么不确定的东西也会有确定的

oracle的null代表的含义是不确定,那么不确定的东西也会有确定的数据类型吗?或者换个说法,null在oracle中的默认数据类型是什么,下面就来探讨这个问题。 首先公布答案, null的默认类型是字符类型,具体是varchar2还是char,这个并不清楚,不过我个人怀疑
oracle的null代表的含义是不确定,那么不确定的东西也会有确定的数据类型吗?或者换个说法,null在oracle中的默认数据类型是什么,下面就来探讨这个问题。
首先公布答案,null的默认类型是字符类型,具体是varchar2还是char,这个并不清楚,不过我个人怀疑是varchar2的可能性更大一些。
我们知道一个字段不管是何种类型的,都可以插入null值,也就是说,null可以随意的转换为任意的类型。
而且,绝大部分的函数输入值为null,返回的结果也为null,这就阻止了我们通过函数的返回结果判断null的类型的企图。我们最常用来分析数据的dump函数,这回也实效了:
sql> select dump(null) from dual;
dump
----
null
而且试图通过create table as来判定null的类型也是不可能的:
sql> create table t as select tname, null col1 from tab;
create table t as select tname, null col1 from tab
*
error 位于第 1 行:
ora-01723: 不允许长度为 0 的列
可能有人会产生疑问,既然各种方法的行不通,你是怎么得到null的默认类型的?也许还有人会想,既然null可以隐式的转化为任意的类型,讨论null的默认类型是否有意义呢?
下面就是我发现null的数据类型的例子,同时说明了如果不注意null的数据类型可能会出现的问题。
由于原始的sql过于复杂,我这里给出一个简化的例子。
sql> create table t (id number);
表已创建。
sql> insert into t values (1);
已创建 1 行。
sql> insert into t values (8);
已创建 1 行。
sql> insert into t values (0);
已创建 1 行。
sql> insert into t values (15);
已创建 1 行。
sql> commit;
提交完成。
需要按照t中的id的升序显示数据,sql如下:
sql> select * from t order by id;
id
----------
0
1
8
15
需求还有一点点小的要求,对于0值这个比较特殊的值,在所有非0值的后面显示。当然实现的方法比较多,比如使用union all将非0值和0值分开,或者将0值转换为一个很大的数值。
由于id的最大值不确定,且考虑使用一个简单的sql完成,我选择了在排序的时候将0值转化为null的方法,这样利用排序时null最大的原理,得到我希望的结果。
sql如下:
sql> select * from t order by decode(id, 0, null, id);
id
----------
1
15
8
0
0值确实如我所愿排在了最后,但是结果怎么“不对”了!
sql> select decode(id, 0, null, id) from t;
decode(id,0,null,id)
----------------------------------------
1
8
15
看看decode函数的结果,这回明白了,原来decode的结果变为了字符类型。字符类型结果在sqlplus显示左对齐,而数值类型是右对齐。
在decode函数中,输入的4个参数中两个id和0都是number类型,只有null这一个输入值类型不确定,莫非是由于null的类型是字符类型?
猜测只是猜测,还需要确切的证据证明这一点,下面看看标准包中decode函数的定义。
下面的decode函数定义是从standard中摘取出来的部分内容:
function decode (expr number, pat number, res number) return number;
function decode (expr number,
pat number,
res varchar2 character set any_cs)
return varchar2 character set res%charset;
function decode (expr number, pat number, res date) return date;
function decode (expr varchar2 character set any_cs,
pat varchar2 character set expr%charset,
res number) return number;
function decode (expr varchar2 character set any_cs,
pat varchar2 character set expr%charset,
res varchar2 character set any_cs)
return varchar2 character set res%charset;
function decode (expr varchar2 character set any_cs,
pat varchar2 character set expr%charset,
res date) return date;
function decode (expr date, pat date, res number) return number;
function decode (expr date,
pat date,
res varchar2 character set any_cs)
return varchar2 character set res%charset;
function decode (expr date, pat date, res date) return date;
通过观察上面的定义,我们不难发现,虽然oracle对decode函数进行了大量的重载,且decode函数支持各种的数据类型,但是decode函数具有一个规律,就是decode函数的返回值的类型和decode函数的输入参数中第一个用来返回的参数的数据类型一致。可能不太好理解,举个简单的例子:
sql> select decode(id, 1, '1', 2) from t;
d
-
1
2
2
2
sql> select decode(id, '1', 1, '2') from t;
decode(id,'1',1,'2')
--------------------
1
2
2
2
从这两个简单的例子就可以看出,decode的返回值的数据类型和decode函数中第一个表示返回的参数的数据类型一致。
从这点就可以看出,null的默认数量类型是字符类型,这才导致decode的结果变成了字符串,而查询根据字符串的排序比较,因此’15’小于’8’。
知道了问题的原因,解决的方法就很多了,比如:
sql> select * from t order by decode(id, 1, 1, 0, null, id);
id
----------
1
8
15
0
sql> select * from t order by to_number(decode(id, 0, null, id));
id
----------
1
8
15
0
sql> select * from t order by decode(id, 0, cast(null as number), id);
id
----------
1
8
15
0
sql> select * from t order by decode(id, 0, to_number(null), id);
id
----------
1
8
15
0
其它类似信息

推荐信息