这个答案可能有点啰嗦……
Oracle对集合操作非常挑剔。每列必须具有与第二个、第三个等查询中相应的数据类型相同的数据类型。
我认为您的第二个查询失败,因为 Oracle在执行之前to_number()
评估为数字,但在. 您的第一个查询成功,因为第一个值已被评估为“null-ness”,然后发生。这意味着评估的顺序是:union
union
- 第一选择功能
- 第一选择数据类型
- 第二选择功能
- 联盟
- 第二选择数据类型
我将尝试一步一步地证明这一点,但我不确定它是否构成绝对证明。
以下两个查询
select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;
由于没有发生隐式转换,将失败并出现以下错误。
ORA-01790: 表达式必须具有与对应表达式相同的数据类型
但是,以下两个都将成功
select null from dual union select '1' from dual;
select null from dual union select 1 from dual;
如果我们选择dump
这两个查询中的一个,则会返回以下内容:
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
如您所见,这些列具有不同的 data-types。第一个查询,有一个字符,返回一个char
,第二个返回一个数字,但是顺序已经颠倒了,第二个select
先来。
最后,如果我们查看dump
您的第一个查询
SQL> select substr(dump(ename),1,35) a, substr(dump(loc),1,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,104,97 NULL
NULL Typ=1 Len=6: 104,97,104,97,104,97
SQL>
你可以看到它dump(to_number(null))
是空的;但 a varchar2
not achar
正在返回,因为这是您的列的数据类型。有趣的是,返回语句的顺序并没有颠倒,如果您将此查询创建为表,则两列都是varchar2
.
在选择查询中确定列的数据类型时,Oracle 采用第一个已知数据类型,然后使用它来计算整体数据类型。这就是为什么第一个select
为空的查询的行被颠倒的原因。
您的第一个查询成功,因为第一个选择select ename,to_number(null) from emp
“描述”了结果集的外观。|varchar2|null|
. 然后第二个查询添加 , |varchar2|varchar2|
,这不会导致任何问题。
您的第二个查询失败,因为第一个选择select ename,to_number(null) from emp
将结果集“描述”为varchar2, null
. 但是,您随后尝试在union
.
这里的信念飞跃是甲骨文决定这to_number(null)
是一个之前的数字union
,直到之后才评估它的“空值”。我真的不知道如何测试这是否真的发生,因为您无法创建带有null
列的对象,并且您注意到您也无法选择它。
因为我无法证明甲骨文不允许的东西,所以我会尝试寻找经验证据。考虑以下查询的结果(或错误)。
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
and to_number
,无论它们是否在 null 上执行,都会隐式定义一个数据类型,然后在union
评估“null-ness”之前评估它在 a 中的适用性
这种解释也将涵盖该coalesce
问题,因为在它为空之前to_number(null)
是一个数字。