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

unionsklausul i sql

Dette svar kan være lidt uoverskueligt...

Oracle er meget kræsen med indstillede operationer. Hver kolonne skal have samme datatype som de tilsvarende i den anden, tredje osv. forespørgsel.

Jeg tror din anden forespørgsel mislykkes, fordi Oracle evaluerer to_number() som et nummer forud til at udføre unionen men vurderer det for "null-ness" efter . Din første forespørgsel lykkes, fordi den første værdi er blevet evalueret for "null-ness" og derefter union opstår. Dette indebærer, at evalueringsrækkefølgen er:

  1. Første valgfunktioner
  2. Første valg af datatyper
  3. Anden valgfunktion
  4. union
  5. Anden udvalgte datatyper

Jeg vil forsøge at bevise dette trin for trin, men jeg er ikke sikker på, at det vil være et absolut bevis.

Begge følgende forespørgsler

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

vil fejle med følgende fejl, da der ikke finder nogen implicit konvertering sted.

Begge følgende vil dog lykkes

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

Hvis vi vælger dump af disse to forespørgsler returneres følgende:

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

Som du kan se har kolonnerne forskellige datatyper . Den første forespørgsel, med et tegn, returnerer et char og den anden returnerer et tal, men rækkefølgen er blevet vendt, med den anden select kommer først.

Til sidst, hvis vi ser på dump af din første forespørgsel

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>

Du kan se den dump(to_number(null)) er nul; men en varchar2 ikke et char bliver returneret, fordi dette er datatypen for din kolonne. Det er interessant at bemærke, at rækkefølgen af ​​de returnerede udsagn ikke er blevet omvendt, og at hvis du skulle oprette denne forespørgsel som en tabel, ville begge kolonner være en varchar2 .

Når du bestemmer datatypen for en kolonne i en udvalgt forespørgsel, tager Oracle den første kendte datatype og bruger den derefter til at beregne den overordnede datatype. Det ville være grunden til, at forespørgslerne var den første select var null havde deres rækker vendt.

Din første forespørgsel lykkes, fordi det første valg, vælg ename,to_number(null) fra emp , "beskriver", hvordan resultatsættet kommer til at se ud. |varchar2|null| . Den anden forespørgsel tilføjer derefter, |varchar2|varchar2| , hvilket ikke giver problemer.

Din anden forespørgsel mislykkes, fordi den første vælger vælg ename,to_number(null) fra emp "beskriver" resultatsættet som varchar2, null . Men du prøver derefter at tilføje et nullnummer og en varchar2 i unionen .

Troens spring her er, at Oracle beslutter, at to_number(null) er et tal forud til unionen og ikke vurdere det for "null-ness" før efter. Jeg ved ikke rigtig, hvordan jeg tester, om dette rent faktisk sker, da du ikke kan oprette et objekt med en null kolonne, og som du bemærker, kan du heller ikke vælge den.

Da jeg ikke kan bevise noget, som Oracle afviser, vil jeg prøve at finde empiriske beviser. Overvej resultaterne (eller fejlene) af følgende forespørgsler.

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

De ser ud til at demonstrere, at to_char og til_nummer , uanset om de udføres på en null, definerer implicit en datatype, som derefter evalueres for dens egnethed i en union , forud for deres evaluering for "null-ness"

Denne forklaring vil også dække sammensmeltning problem som to_number(null) er et tal før det er et nul.




  1. PostgreSQL - hvordan kører man VACUUM fra kode uden for transaktionsblok?

  2. MySQL og Splunk - Vælg og deltag

  3. hvordan udløses en opdatering på en tabelrækkeværdi ved hjælp af en rækkeværdi fra en anden tabel i Apex Oracle SQL?

  4. Hvordan kan jeg sætte IF ELSE CONDITION i Oracle-forespørgsel?