Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

cláusula de união em sql


Essa resposta pode ser um pouco confusa...

A Oracle é muito exigente com operações de conjunto. Cada coluna deve ter o mesmo tipo de dados que os correspondentes na segunda, terceira consulta etc.

Eu acho sua segunda consulta falha porque o Oracle avalia to_number() como um número anterior para realizar a union mas avalia-o para "null-ness" depois . Sua primeira consulta foi bem-sucedida porque o primeiro valor foi avaliado para "null-ness" e, em seguida, o union ocorre. Isso implica que a ordem de avaliação é:
  1. 1ª seleção de funções
  2. Primeira seleção de tipos de dados
  3. 2ª seleção de funções
  4. sindicato
  5. Segundo tipos de dados selecionados

Vou tentar provar isso passo a passo, mas não tenho certeza se será uma prova absoluta.

Ambas as consultas a seguir
select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;

falhará com o seguinte erro, pois nenhuma conversão implícita ocorre.

No entanto, ambos os itens a seguir serão bem-sucedidos
select null from dual union select '1' from dual;
select null from dual union select 1 from dual;

Se selecionarmos o dump dessas duas consultas, o seguinte é retornado:
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

Como você pode ver, as colunas têm diferentes tipos de dados . A primeira consulta, com um caractere, retorna um char e o segundo retorna um número, mas a ordem foi invertida, com o segundo select vindo primeiro.

Por último, se olharmos para dump da sua primeira consulta
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>

Você pode ver que dump(to_number(null)) é nulo; mas um varchar2 não um char está sendo retornado, porque este é o tipo de dados de sua coluna. É interessante notar que a ordem das declarações retornadas não foi invertida e que se você criasse esta consulta como uma tabela ambas as colunas seriam um varchar2 .

Ao decidir o tipo de dados de uma coluna em uma consulta selecionada, o Oracle usa o primeiro tipo de dados conhecido e o usa para calcular o tipo de dados geral. Seria por isso que as consultas onde o primeiro select foi null tiveram suas linhas invertidas.

Sua primeira consulta foi bem-sucedida porque a primeira seleção, select ename,to_number(null) from emp , "descreve" como será o conjunto de resultados. |varchar2|null| . A segunda consulta adiciona, |varchar2|varchar2| , o que não causa problemas.

Sua segunda consulta falha porque a primeira seleciona select ename,to_number(null) from emp "descreve" o conjunto de resultados como varchar2, null . No entanto, você tenta adicionar um número nulo e um varchar2 no union .

O salto de fé aqui é que a Oracle está decidindo que to_number(null) é um número anterior para a union e não avaliá-lo para "null-ness" até depois. Eu realmente não sei como testar se isso está realmente acontecendo, pois você não pode criar um objeto com um null coluna e, como você observa, também não pode selecioná-la.

Como não posso provar algo que a Oracle não permite, vou tentar evidências empíricas. Considere os resultados (ou erros) das consultas a seguir.
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

Eles parecem demonstrar que to_char e to_number , não importa se eles são executados em um nulo, definem implicitamente um tipo de dados que é avaliado quanto à sua adequação em um union , antes de sua avaliação para "nulidade"

Esta explicação também abrangeria a coalesce problema como o to_number(null) é um número antes é um nulo.