Oracle
 sql >> Database >  >> RDS >> Oracle

clausola di unione in sql

Questa risposta potrebbe essere un po' sconclusionata...

Oracle è molto schizzinoso con le operazioni sugli insiemi. Ogni colonna deve avere lo stesso tipo di dati di quelle corrispondenti nella seconda, terza query ecc.

penso la tua seconda query ha esito negativo perché Oracle valuta to_number() come numero precedente per eseguire l'union ma lo valuta per "nullità" dopo . La tua prima query ha esito positivo perché il primo valore è stato valutato per "null-ness" e quindi per union si verifica. Ciò implica che l'ordine di valutazione è:

  1. Prima selezione funzioni
  2. Prima selezione dei tipi di dati
  3. 2a funzione di selezione
  4. unione
  5. 2a selezione dei tipi di dati

Cercherò di dimostrarlo passo dopo passo, ma non sono sicuro che rappresenterà una prova assoluta.

Entrambe le seguenti query

select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;

fallirà con il seguente errore poiché non ha luogo alcuna conversione implicita.

Tuttavia, entrambi i seguenti avranno successo

select null from dual union select '1' from dual;
select null from dual union select 1 from dual;

Se selezioniamo dump di queste due query viene restituito quanto segue:

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

Come puoi vedere, le colonne hanno diversi tipi di dati . La prima query, con un carattere, restituisce un char e il secondo restituisce un numero, ma l'ordine è stato invertito, con il secondo select primo arrivato.

Infine, se guardiamo a dump della tua prima domanda

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>

Puoi vedere che dump(to_number(null)) è zero; ma un varchar2 non un char viene restituito, perché questo è il tipo di dati della colonna. È interessante notare che l'ordine delle istruzioni restituite non è stato invertito e che se dovessi creare questa query come tabella entrambe le colonne sarebbero un varchar2 .

Quando si decide il tipo di dati di una colonna in una query selezionata, Oracle prende il primo tipo di dati noto e quindi lo utilizza per calcolare il tipo di dati complessivo. Questo sarebbe il motivo per cui le query in cui il primo select era null le loro righe erano state invertite.

La tua prima query ha esito positivo perché la prima selezione, select ename,to_number(null) from emp , "descrive" come apparirà il set di risultati. |varchar2|null| . La seconda query aggiunge quindi |varchar2|varchar2| , che non causa problemi.

La tua seconda query ha esito negativo perché la prima select select ename,to_number(null) from emp "descrive" il set di risultati come varchar2, null . Tuttavia, provi quindi ad aggiungere un numero null e un varchar2 in union .

Il salto di fede qui è che Oracle sta decidendo che to_number(null) è un numero anteriore al union e non valutarlo per "nullità" fino a dopo. Non so davvero come verificare se ciò stia effettivamente accadendo poiché non puoi creare un oggetto con un null colonna e come noterai non puoi nemmeno selezionarla.

Poiché non posso provare qualcosa che Oracle non consente, cercherò prove empiriche. Considera i risultati (o gli errori) delle seguenti query.

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

Sembrano dimostrare che to_char e to_number , indipendentemente dal fatto che vengano eseguiti su un null, definiscono implicitamente un tipo di dati che viene quindi valutato per la sua idoneità in un union , prima della loro valutazione per "nullità"

Questa spiegazione riguarderebbe anche il coalesce problema come to_number(null) è un numero prima è un nullo.