emp : ename varchar2(25) dept: loc varchar2(25)
我有以下3例:
select ename,to_number(null) from emp union select to_char(null),loc from dept;
select ename,to_number(null) from emp union select to_number(null),null from emp union select null,loc from dept;
情况1完全执行.
情况2无法执行.
情况3也完美执行.
我的理解是,我们需要确保,如果没有相应的联盟列,那么我们需要创建一个等效的数据类型虚拟.因此,一个数字类型在另一个表的相应列表中具有类似to_number(null)的东西.
在情况3中,我们指定所有的null,所以我有点了解情况.但是在情况1中,loc和to_number之间没有数据类型兼容性,但是它执行.另一方面,案例2失败.请澄清.
解决方法
Oracle在设置操作时非常挑剔.每列必须具有与第二,第三等查询中相应数据类型相同的数据类型.
我认为您的第二个查询失败,因为在执行union之前,Oracle将to_number()作为一个数值进行评估,之后将其评估为“null-ness”.您的第一个查询成功,因为第一个值已被评估为“null-ness”,然后发生联合.这意味着评估的顺序是:
>第一选择功能@H_502_29@>第一选择数据类型@H_502_29@>第二选择功能@H_502_29@>联盟@H_502_29@>第二选择数据类型
我会尝试证明这一步一步,但我不知道这将是一个绝对的证明.
以下两个查询
select 1 from dual union select '1' from dual; select '1' from dual union select 1 from dual;
将失败并出现以下错误,因为不会发生隐式转换.
ORA-01790: expression must have same datatype as corresponding@H_502_29@ expression
但是,以下将成功
select null from dual union select '1' from dual; select null from dual union select 1 from dual;
sql> select dump(a) 2 from ( select null a from dual union select '1' from dual ); DUMP(A) ------------------------------------------------------------------- Typ=96 Len=1: 49 NULL sql> select dump(a) 2 from ( select null a from dual union select 1 from dual ); DUMP(A) ------------------------------------------------------------------- Typ=2 Len=2: 193,2 NULL
正如你可以看到列有different data-types.第一个查询,一个字符,返回一个字符,第二个返回一个数字,但是顺序已经转过来,第二个选择是第一个.
最后,如果我们看看你的第一个查询的转储
sql> select substr(dump(ename),1,35) a,substr(dump(loc),35) b 2 from ( select ename,to_number(null) as loc from emp 3 union 4 select to_char(null),loc from dept 5 ); A B ----------------------------------- ----------------------------------- Typ=1 Len=6: 104,97,104,97 NULL NULL Typ=1 Len=6: 104,97 sql>
你可以看到dump(to_number(null))为null;但是varchar2没有返回char,因为这是列的数据类型.有趣的是,返回的语句的顺序并没有被颠倒,如果要将这个查询创建为一个表,那么两列都是一个varchar2.
在选择查询中决定列的数据类型时,Oracle会采用第一个已知的数据类型,然后使用该数据类型来计算整体数据类型.这就是为什么第一个select为空的查询的行被颠倒了.
您的第一个查询成功,因为第一个select,select ename,to_number(null)from emp,“描述”结果集将是什么样子. | VARCHAR2 |空|.然后,第二个查询将添加| varchar2 | varchar2 |,这样就不会出现问题.
您的第二个查询失败,因为第一个select select ename,to_number(null)from emp“将”结果集描述为varchar2,null.但是,然后尝试在联合中添加一个空号和一个varchar2.
信仰的飞跃是,Oracle正在决定to_number(null)是联合之前的一个数字,直到之后才对“null-ness”进行评估.我真的不知道如何测试这是否实际发生,因为您无法创建一个空列的对象,并且您注意到您也无法选择它.
因为我不能证明Oracle不允许的东西,我会尝试实证证据.考虑以下查询的结果(或错误).
sql> select 1 as a from dual union select to_number(null) from dual; A ---------- 1 sql> select '1' as a from dual union select to_number(null) from dual; select '1' as a from dual union select to_number(null) from dual * ERROR at line 1: ORA-01790: expression must have same datatype as corresponding expression sql> select 1 as a from dual union select to_char(null) from dual; select 1 as a from dual union select to_char(null) from dual * ERROR at line 1: ORA-01790: expression must have same datatype as corresponding expression sql> select '1' as a from dual union select to_char(null) from dual; A - 1
他们似乎演示了to_char和to_number,无论它们是否在一个null上执行,隐含地定义一个数据类型,然后在对“null-ness”进行评估之前对其适用性进行评估,
此解释也将涵盖合并问题,因为to_number(null)是一个数字,它是一个null.