sql >> Databasteknik >  >> RDS >> Oracle

unionsklausul i sql

Det här svaret kan vara lite klurigt...

Oracle är mycket kräsen med inställda operationer. Varje kolumn måste ha samma datatyp som motsvarande i den andra, tredje osv. frågan.

Jag tror din andra fråga misslyckas eftersom Oracle utvärderar to_number() som ett nummer före för att utföra unionen men utvärderar det för "null-ness" efter . Din första fråga lyckas eftersom det första värdet har utvärderats för "null-ness" och sedan union inträffar. Detta innebär att utvärderingsordningen är:

  1. Första valda funktioner
  2. Första val av datatyper
  3. Andra valfunktioner
  4. fackförening
  5. Andra val av datatyper

Jag ska försöka bevisa detta steg för steg, men jag är inte säker på att det kommer att vara ett absolut bevis.

Båda följande frågor

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

kommer att misslyckas med följande fel eftersom ingen implicit konvertering äger rum.

Men båda följande kommer att lyckas

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

Om vi ​​väljer dump av dessa två frågor returneras följande:

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 kolumnerna olika datatyper . Den första frågan, med ett tecken, returnerar ett char och den andra returnerar ett nummer, men ordningen har vänts, med den andra select kommer först.

Slutligen, om vi tittar på dump av din första fråga

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)) är inget; men en varchar2 inte en char returneras, eftersom detta är datatypen för din kolumn. Det är intressant att notera att ordningen på de returnerade satserna inte har omvänts och att om du skulle skapa den här frågan som en tabell skulle båda kolumnerna vara en varchar2 .

När du bestämmer datatypen för en kolumn i en urvalsfråga tar Oracle den första kända datatypen och använder den sedan för att beräkna den övergripande datatypen. Det skulle vara anledningen till att frågorna var den första välj var null hade sina rader omvända.

Din första fråga lyckas eftersom den första valen, välj ename,to_number(null) från emp , "beskriver" hur resultatuppsättningen kommer att se ut. |varchar2|null| . Den andra frågan lägger sedan till |varchar2|varchar2| , vilket inte orsakar några problem.

Din andra fråga misslyckas eftersom den första väljer välj ename,to_number(null) från emp "beskriver" resultatuppsättningen som varchar2, null . Men du försöker sedan lägga till ett nullnummer och en varchar2 i unionen .

Trosprånget här är att Oracle bestämmer att to_number(null) är ett nummer före till unionen och inte utvärdera det för "nullhet" förrän efter. Jag vet inte riktigt hur man testar om detta verkligen händer eftersom du inte kan skapa ett objekt med en null kolumn och som du noterar kan du inte välja den heller.

Eftersom jag inte kan bevisa något som Oracle inte tillåter ska jag försöka hitta empiriska bevis. Tänk på resultaten (eller felen) av följande frågor.

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 verkar visa att to_char och to_number , oavsett om de utförs på en noll definierar implicit en datatyp som sedan utvärderas för dess lämplighet i en union , innan de bedöms för "null-ness"

Den här förklaringen skulle också täcka sammansmält problemet som to_number(null) är ett nummer före det är en noll.




  1. exempel på oracle join syntax

  2. Hur lagrar man födelsedatum och ålder så att ålder kan uppdateras dagligen i PHP/MySQL?

  3. regexp_substr hoppar över tomma positioner

  4. Vila kriterier för få poster som har år 2012