Cette réponse peut être un peu décousue...
Oracle est très pointilleux avec des opérations définies. Chaque colonne doit avoir le même type de données que celles correspondantes dans les deuxième, troisième requêtes, etc.
Je pense votre deuxième requête échoue car Oracle évalue to_number()
comme un nombre précédent pour effectuer l'union
mais l'évalue pour "null-ness" après . Votre première requête réussit car la première valeur a été évaluée pour "null-ness", puis l'union
se produit. Cela implique que l'ordre d'évaluation est :
- 1ère sélection de fonctions
- Première sélection des types de données
- 2e fonctions de sélection
- syndicat
- 2e sélectionner les types de données
Je vais essayer de le prouver étape par étape, mais je ne suis pas sûr que cela constituera une preuve absolue.
Les deux requêtes suivantes
select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;
échouera avec l'erreur suivante car aucune conversion implicite n'a lieu.
Cependant, les deux éléments suivants réussiront
select null from dual union select '1' from dual;
select null from dual union select 1 from dual;
Si nous sélectionnons le dump
de ces deux requêtes, la suivante est renvoyée :
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
Comme vous pouvez le voir, les colonnes ont différents types de données
. La première requête, avec un caractère, retourne un char
et le second renvoie un nombre, mais la commande a été inversée, avec le second select
venir en premier.
Enfin, si nous regardons dump
de votre première requête
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>
Vous pouvez voir que dump(to_number(null))
est nul ; mais un varchar2
pas un char
est renvoyé, car il s'agit du type de données de votre colonne. Il est intéressant de noter que l'ordre des instructions renvoyées n'a pas été inversé et que si vous deviez créer cette requête en tant que table, les deux colonnes seraient un varchar2
.
Lors de la décision du type de données d'une colonne dans une requête de sélection, Oracle prend le premier type de données connu, puis l'utilise pour calculer le type de données global. Ce serait pourquoi les requêtes où le premier select
était null avaient leurs lignes inversées.
Votre première requête réussit car la première sélection, select ename,to_number(null) from emp
, "décrit" à quoi ressemblera le jeu de résultats. |varchar2|null|
. La deuxième requête ajoute alors, |varchar2|varchar2|
, ce qui ne pose aucun problème.
Votre deuxième requête échoue car la première sélection select ename,to_number(null) from emp
"décrit" le jeu de résultats comme varchar2, null
. Cependant, vous essayez ensuite d'ajouter un nombre nul et un varchar2 dans le union
.
L'acte de foi ici est qu'Oracle décide que to_number(null)
est un nombre antérieur au union
et ne pas l'évaluer pour la "nullité" jusqu'à après. Je ne sais pas vraiment comment tester si cela se produit réellement car vous ne pouvez pas créer un objet avec un null
colonne et comme vous le notez, vous ne pouvez pas le sélectionner non plus.
Comme je ne peux pas prouver quelque chose qu'Oracle interdit, je vais essayer d'obtenir des preuves empiriques. Tenez compte des résultats (ou des erreurs) des requêtes suivantes.
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
Ils semblent démontrer que to_char
et to_number
, qu'ils soient exécutés sur un null définissent implicitement un type de données qui est ensuite évalué pour sa pertinence dans une union
, avant leur évaluation pour "null-ness"
Cette explication couvrirait également la coalesce
issue comme to_number(null)
est un nombre devant c'est un nul.