sql中的union子句

时间:2012-08-21 15:00:16

标签: sql oracle union

给出以下表格描述:

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),loc from dept;

  select ename,null from emp
    union
    select null,loc from dept;

案例1完美执行。

案例2无法执行。

案例3也完美地执行。

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

在第3种情况下,我们指定所有null,所以我有点理解这个场景。但在案例1中,locto_number之间没有数据类型兼容性,但它会执行。另一方面,案例2失败。请澄清。

1 个答案:

答案 0 :(得分:8)

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

Oracle使用set操作非常挑剔。每列必须与第二个,第三个等查询中的相应数据类型相同。

认为您的第二个查询失败,因为Oracle将to_number()评估为之前的 以执行union,但将其评估为“null- 之后的。您的第一个查询成功,因为已经为“null-ness”评估了第一个值,然后发生了union。这意味着评估的顺序是:

  1. 第一选择功能
  2. 第一个选择数据类型
  3. 第二选择功能
  4. 联合
  5. 第二选择数据类型
  6. 我会尝试逐步证明这一点,但我不确定它是否足以证明这一点。

    以下两个查询

    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
    

    正如您所见,列有different 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))为空;但是返回了varchar2而不是char,因为这是列的数据类型。有趣的是,请注意返回的语句的顺序没有被反转,如果您要将此查询创建为表,则两列都将是varchar2

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

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

    您的第二个查询失败,因为第一个选择select ename,to_number(null) from emp“将结果集描述为varchar2, null。但是,您尝试在union中添加空数和varchar2。

    这里的信念的飞跃是Oracle决定to_number(null)之前 的数字union而不是之前评估它为“null-ness”。我真的不知道如何测试这是否真的发生,因为你无法创建一个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_charto_number,无论它们是否在null上执行,都会隐式定义数据类型,然后根据union评估它的适用性,在评估“无效”之前

    此解释也会涵盖coalesce问题,因为to_number(null)是一个数字,之后为空。