Tato odpověď může být trochu nesourodá...
Oracle je velmi vybíravý s nastavenými operacemi. Každý sloupec musí mít stejný datový typ jako odpovídající sloupce ve druhém, třetím atd. dotazu.
Myslím váš druhý dotaz selže, protože Oracle vyhodnotí to_number()
jako číslo předchozí k provedení union
ale vyhodnotí ji jako "nulovou" po . Váš první dotaz byl úspěšný, protože první hodnota byla vyhodnocena jako "null-ness" a poté union
dochází. To znamená, že pořadí hodnocení je:
- První výběr funkcí
- První výběr datových typů
- 2. výběr funkcí
- spojení
- 2. výběr datových typů
Pokusím se to dokázat krok za krokem, ale nejsem si jistý, zda to bude absolutní důkaz.
Oba následující dotazy
select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;
selže s následující chybou, protože neprobíhá žádná implicitní konverze.
Oba následující však uspějí
select null from dual union select '1' from dual;
select null from dual union select 1 from dual;
Pokud vybereme dump
z těchto dvou dotazů se vrátí následující:
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
Jak můžete vidět, sloupce mají různé datové typy
. První dotaz se znakem vrátí char
a druhý vrátí číslo, ale pořadí bylo obráceno, s druhým select
na prvním místě.
Nakonec, když se podíváme na dump
vašeho prvního dotazu
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>
Můžete vidět, že dump(to_number(null))
je null; ale varchar2
ne char
se vrací, protože se jedná o datový typ vašeho sloupce. Je zajímavé poznamenat, že pořadí vrácených příkazů nebylo obráceno a že pokud byste tento dotaz vytvořili jako tabulku, oba sloupce by byly varchar2
.
Při rozhodování o datovém typu sloupce ve výběrovém dotazu Oracle vezme první známý datový typ a poté jej použije k výpočtu celkového datového typu. To by byl důvod, proč dotazy, kde první select
byla nulová a jejich řádky byly obráceny.
Váš první dotaz byl úspěšný, protože první vyberte, select ename,to_number(null) from emp
, "popisuje", jak bude výsledná sada vypadat. |varchar2|null|
. Druhý dotaz pak přidá |varchar2|varchar2|
, což nezpůsobuje žádné problémy.
Váš druhý dotaz se nezdařil, protože první vyberte select ename,to_number(null) from emp
"popisuje" sadu výsledků jako varchar2, null
. Potom se však pokusíte přidat číslo null a varchar2 do union
.
Skok víry je v tom, že Oracle rozhoduje o tom, že to_number(null)
je číslo předchozí do union
a nevyhodnocovat ji jako „nulovost“ až poté. Opravdu nevím, jak otestovat, zda se to skutečně děje, protože nemůžete vytvořit objekt s null
a jak jste si všimli, nemůžete jej vybrat ani.
Protože nemohu dokázat něco, co Oracle nepovoluje, pokusím se o empirický důkaz. Zvažte výsledky (nebo chyby) následujících dotazů.
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
Zdá se, že demonstrují, že to_char
a to_number
, bez ohledu na to, zda jsou prováděny na hodnotě null, implicitně definují datový typ, který je následně vyhodnocen z hlediska vhodnosti v union
, před jejich vyhodnocením na "nulovost"
Toto vysvětlení by také pokrývalo coalesce
problém jako to_number(null)
je číslo před je null.