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ª seleção de funções
- Primeira seleção de tipos de dados
- 2ª seleção de funções
- sindicato
- 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.