sql中的union子句

Kaz*_*ara 12 sql oracle union

给出下表描述:

emp : 

ename varchar2(25)


dept:

loc varchar2(25)
Run Code Online (Sandbox Code Playgroud)

我有以下3个案例:

select ename,to_number(null) from emp
union
select to_char(null),loc from dept;
Run Code Online (Sandbox Code Playgroud)
  select ename,to_number(null) from emp
    union
    select to_number(null),loc from dept;
Run Code Online (Sandbox Code Playgroud)
  select ename,null from emp
    union
    select null,loc from dept;
Run Code Online (Sandbox Code Playgroud)

案例1完美执行.

案例2未能执行.

案例3也完美地执行.

我的理解是,我们需要确保如果联合没有相应的列,那么我们需要创建一个等效的数据类型dummy.因此,number类型具有类似于to_number(null)另一个表的相应列列表中的类型.

在案例3中,我们指定所有null,所以我有点理解该场景.但在案例1中,loc和之间没有数据类型兼容性to_number,但它会执行.另一方面,案例2失败.请澄清.

Ben*_*Ben 8

这个答案可能有点散漫......

Oracle 对设置操作非常挑剔.每列必须与第二个,第三个等查询中的相应数据类型相同.

因为Oracle评估你的第二个查询失败to_number()多项之前在执行union,但评估它与"空性" 之后.您的第一个查询成功,因为第一个值已经评估为"null-ness"然后union发生.这意味着评估的顺序是:

  1. 第一选择功能
  2. 第一个选择数据类型
  3. 第二选择功能
  4. 联盟
  5. 第二选择数据类型

我将尝试逐步证明这一点,但我不确定它是否足以证明这一点.

以下两个查询

select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;
Run Code Online (Sandbox Code Playgroud)

将因以下错误而失败,因为不会发生隐式转换.

ORA-01790:表达式必须与相应的表达式具有相同的数据类型

但是,以下两个都将成功

select null from dual union select '1' from dual;
select null from dual union select 1 from dual;
Run Code Online (Sandbox Code Playgroud)

如果我们选择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
Run Code Online (Sandbox Code Playgroud)

如您所见,列具有不同的数据类型.带有字符的第一个查询返回a 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>
Run Code Online (Sandbox Code Playgroud)

你可以看到它dump(to_number(null))是null; 但是varchar2char返回a,因为这是列的数据类型.这是有趣的是,返回的语句的顺序没有被逆转,如果你要创建这个查询作为表两列将是一个varchar2.

在选择查询中确定列的数据类型时,Oracle采用第一个已知数据类型,然后使用它来计算整体数据类型.这就是为什么第一个select为null 的查询的行被反转的原因.

您的第一个查询成功,因为第一个选择,select ename,to_number(null) from emp"描述"结果集的外观.|varchar2|null|.然后第二个查询添加|varchar2|varchar2|,这不会导致任何问题.

您的第二个查询失败,因为第一个选择select ename,to_number(null) from emp"描述"结果集为varchar2, null.但是,然后尝试在中添加空数和varchar2 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
Run Code Online (Sandbox Code Playgroud)

它们似乎证明了这一点,to_char并且to_number,无论它们是否在null上执行,都会隐式定义一个数据类型,然后在union评估"null-ness"之前对其进行评估,以确定它是否合适.

这个解释也将涵盖coalesce问题,因为它to_number(null)是一个数字,然后它是一个空值.