Oracle
 sql >> Datenbank >  >> RDS >> Oracle

union-Klausel in sql

Diese Antwort ist vielleicht etwas weitschweifig...

Oracle ist sehr wählerisch bei Mengenoperationen. Jede Spalte muss denselben Datentyp haben wie die entsprechenden Spalten in der zweiten, dritten usw. Abfrage.

Ich denke Ihre zweite Abfrage schlägt fehl, weil Oracle to_number() auswertet als Zahl vorher um die union durchzuführen wertet es aber auf "Nullheit" nach aus . Ihre erste Abfrage ist erfolgreich, da der erste Wert auf "Nullheit" und dann auf union ausgewertet wurde tritt ein. Dies impliziert, dass die Auswertungsreihenfolge wie folgt lautet:

  1. 1. Funktionen auswählen
  2. 1. Datentypen auswählen
  3. Zweite Auswahlfunktionen
  4. Gewerkschaft
  5. 2. Datentypen auswählen

Ich werde versuchen, dies Schritt für Schritt zu beweisen, aber ich bin mir nicht sicher, ob es ein absoluter Beweis sein wird.

Die beiden folgenden Abfragen

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

schlägt mit dem folgenden Fehler fehl, da keine implizite Konvertierung stattfindet.

Die beiden folgenden werden jedoch erfolgreich sein

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

Wenn wir dump Von diesen beiden Abfragen wird Folgendes zurückgegeben:

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

Wie Sie sehen können, haben die Spalten unterschiedliche Datentypen . Die erste Abfrage mit einem Zeichen gibt ein char zurück und der zweite gibt eine Zahl zurück, aber die Reihenfolge wurde umgekehrt, mit dem zweiten select kommt zuerst.

Zuletzt, wenn wir uns dump ansehen Ihrer ersten Anfrage

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>

Sie können diesen dump(to_number(null)) sehen ist Null; sondern ein varchar2 kein char zurückgegeben wird, da dies der Datentyp Ihrer Spalte ist. Es ist interessant festzustellen, dass die Reihenfolge der zurückgegebenen Anweisungen nicht umgekehrt wurde und dass beide Spalten ein varchar2 wären, wenn Sie diese Abfrage als Tabelle erstellen würden .

Bei der Entscheidung über den Datentyp einer Spalte in einer Auswahlabfrage nimmt Oracle den ersten bekannten Datentyp und verwendet diesen dann zur Berechnung des Gesamtdatentyps. Dies wäre der Grund, warum die Abfragen das erste select sind war null hatte ihre Zeilen umgekehrt.

Ihre erste Abfrage ist erfolgreich, weil der erste select, select ename,to_number(null) from emp , "beschreibt", wie die Ergebnismenge aussehen wird. |varchar2|null| . Die zweite Abfrage fügt dann hinzu, |varchar2|varchar2| , was keine Probleme verursacht.

Ihre zweite Abfrage schlägt fehl, weil die erste select select ename,to_number(null) from emp "beschreibt" die Ergebnismenge als varchar2, null . Allerdings versuchen Sie dann, eine Nullzahl und eine varchar2 in union einzufügen .

Der Vertrauensvorschuss hier ist, dass Oracle entscheidet, dass to_number(null) ist eine Zahl vorher zur union und erst danach auf "Nullheit" auswerten. Ich weiß nicht wirklich, wie ich testen soll, ob dies tatsächlich passiert, da Sie kein Objekt mit einem null erstellen können Spalte und wie Sie bemerken, können Sie sie auch nicht auswählen.

Da ich etwas nicht beweisen kann, was Oracle nicht zulässt, versuche ich es mit empirischen Beweisen. Betrachten Sie die Ergebnisse (oder Fehler) der folgenden Abfragen.

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

Sie scheinen zu demonstrieren, dass to_char und to_number , unabhängig davon, ob sie auf Null ausgeführt werden, definieren implizit einen Datentyp, der dann in einer union auf seine Eignung hin ausgewertet wird , vor ihrer Bewertung auf "Nullheit"

Diese Erklärung würde auch coalesce abdecken Ausgabe als to_number(null) ist eine Zahl vor es ist eine Null.