首页 > Linux操作系统 > Linux操作系统 > NULL的数据类型(二)
以前写过一篇文章,通过DECODE来确定NULL的默认数据类型,前几天在开发版发现newkid通过不同的方法得出了相同的答案。
NULL的数据类型:http://yangtingkun.itpub.net/post/468/50132
ITPUB中原贴:http://www.itpub.net/thread-1328690-1-1.html
NULL比较特殊,任何数据类型的空都用NULL来表示,因此NULL可以是任何数据类型。所以在一般情况下,NULL也是不会体现出具体的类型的。
不过有时候还是可以从一些特殊的情况判断出Oracle给NULL确定的默认类型。
比如newkid给出的CREATE VIEW的例子:
SQL> CREATE VIEW V_NULL AS
2 SELECT NULL N
3 FROM DUAL;
视图已创建。
SQL> DESC V_NULL
名称 是否为空? 类型
------------------------------------------------------- -------- --------
N VARCHAR2
和我前一篇得出的结果是一样的,Oracle在某些情况下,会把NULL当作VARCHAR2类型来处理。
而且同时还发现几个有意思的现象:
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT SYSDATE N FROM DUAL
3 UNION ALL
4 SELECT NULL FROM DUAL;
视图已创建。
SQL> DESC V_TEST
名称 是否为空? 类型
------------------------------------------------------- -------- --------------
N DATE
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT SYSDATE N FROM DUAL
3 UNION ALL
4 SELECT '' FROM DUAL;
SELECT SYSDATE N FROM DUAL
*
第 2 行出现错误:
ORA-01790: 表达式必须具有与对应表达式相同的数据类型
Oracle会检查UNION ALL包含的两个查询结果的数据类型是否匹配,如果不匹配就会出现上面的错误。其实在以前的文章中已经提到过,空字符串‘‘是NULL的字符类型表现形式,具体的描述可以参考:http://yangtingkun.itpub.net/post/468/245697
由于NULL可以转换为任意的类型,因此Oracle检查到NULL后,会根据另一个查询的类型来确定最终的类型,但是空字符串‘‘已经表现出了字符类型,因此和另一个查询的DATE类型不相符因此报错。
重点是下面的结果:
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT NULL N FROM DUAL
3 UNION ALL
4 SELECT '' FROM DUAL;
视图已创建。
SQL> DESC V_TEST
名称 是否为空? 类型
------------------------------------------------------- -------- ----------------
N VARCHAR2
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT '' N FROM DUAL
3 UNION ALL
4 SELECT NULL FROM DUAL;
视图已创建。
SQL> DESC V_TEST
名称 是否为空? 类型
------------------------------------------------------- -------- ----------------
N CHAR
两个SQL的区别只是UNION ALL两个查询的顺序,而恰恰就是这个顺序决定了最终视图中字段的类型。从这一个SQL可以得出三个推论,一、UNION ALL查询由前面的SQL作为类型的主导;二、空字符串’’的默认类型是CHAR;三、NULL的默认类型是VARCHAR2。
除了上面的结果外,TO_NUMBER(NULL)也比较有意思:
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT TO_NUMBER(NULL) N FROM DUAL
3 UNION ALL
4 SELECT TO_CHAR(NULL) FROM DUAL;
视图已创建。
SQL> DESC V_TEST
名称 是否为空? 类型
------------------------------------------------------- -------- ---------------------
N VARCHAR2
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT TO_NUMBER(NULL) N FROM DUAL
3 UNION ALL
4 SELECT TO_DATE(NULL) FROM DUAL;
视图已创建。
SQL> DESC V_TEST
名称 是否为空? 类型
------------------------------------------------------- -------- ---------------------
N DATE
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT TO_CHAR(NULL) N FROM DUAL
3 UNION ALL
4 SELECT TO_NUMBER(NULL) FROM DUAL;
SELECT TO_CHAR(NULL) N FROM DUAL
*
第 2 行出现错误:
ORA-01790: 表达式必须具有与对应表达式相同的数据类型
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT TO_CHAR(NULL) N FROM DUAL
3 UNION ALL
4 SELECT TO_DATE(NULL) FROM DUAL;
SELECT TO_CHAR(NULL) N FROM DUAL
*
第 2 行出现错误:
ORA-01790: 表达式必须具有与对应表达式相同的数据类型
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT TO_DATE(NULL) N FROM DUAL
3 UNION ALL
4 SELECT TO_NUMBER(NULL) FROM DUAL;
SELECT TO_DATE(NULL) N FROM DUAL
*
第 2 行出现错误:
ORA-01790: 表达式必须具有与对应表达式相同的数据类型
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT TO_DATE(NULL) N FROM DUAL
3 UNION ALL
4 SELECT TO_CHAR(NULL) FROM DUAL;
SELECT TO_DATE(NULL) N FROM DUAL
*
第 2 行出现错误:
ORA-01790: 表达式必须具有与对应表达式相同的数据类型
似乎在UNION ALL第一个查询中指定的TO_NUMBER没有起到确定NUMBER类型的作用,而如果缓冲CAST则不会出现这种情况:
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT CAST(NULL AS NUMBER) N FROM DUAL
3 UNION ALL
4 SELECT TO_CHAR(NULL) FROM DUAL;
SELECT CAST(NULL AS NUMBER) N FROM DUAL
*
第 2 行出现错误:
ORA-01790: 表达式必须具有与对应表达式相同的数据类型
但是要是TO_NUMBER一点作用都没有也不尽然:
SQL> CREATE OR REPLACE VIEW V_TEST AS
2 SELECT TO_NUMBER(NULL) N FROM DUAL
3 UNION ALL
4 SELECT NULL FROM DUAL;
视图已创建。
SQL> DESC V_TEST
名称 是否为空? 类型
------------------------------------------------------- -------- -------------------
N NUMBER
总之,NULL总会给我们带来一些意想不到东西。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-670308/ ,如需转载,请注明出处,否则将追究法律责任。