Jawaban ini mungkin sedikit bertele-tele...
Oracle sangat pilih-pilih dengan operasi yang ditetapkan. Setiap kolom harus memiliki tipe data yang sama dengan yang terkait di kueri kedua, ketiga, dll.
Saya berpikir kueri kedua Anda gagal karena Oracle mengevaluasi to_number()
sebagai nomor sebelumnya untuk melakukan union
tetapi mengevaluasinya untuk "null-ness" setelah . Kueri pertama Anda berhasil karena nilai pertama telah dievaluasi untuk "null-ness" dan kemudian union
terjadi. Ini menyiratkan bahwa urutan evaluasi adalah:
- fungsi pilihan pertama
- Pilih tipe data pertama
- fungsi pilihan kedua
- serikat
- kedua pilih tipe data
Saya akan mencoba membuktikan ini selangkah demi selangkah, tetapi saya tidak yakin itu akan menjadi bukti yang mutlak.
Kedua pertanyaan berikut
select 1 from dual union select '1' from dual;
select '1' from dual union select 1 from dual;
akan gagal dengan kesalahan berikut karena tidak ada konversi implisit yang terjadi.
Namun, kedua hal berikut akan berhasil
select null from dual union select '1' from dual;
select null from dual union select 1 from dual;
Jika kita memilih dump
dari dua pertanyaan ini, berikut ini akan dikembalikan:
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
Seperti yang Anda lihat, kolom memiliki tipe data yang berbeda
. Kueri pertama, dengan karakter, mengembalikan char
dan yang kedua mengembalikan angka, tetapi urutannya telah dibalik, dengan select
second kedua datang lebih dulu.
Terakhir, jika kita melihat dump
dari kueri pertama Anda
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>
Anda dapat melihat dump(to_number(null))
adalah nol; tapi varchar2
bukan char
dikembalikan, karena ini adalah tipe data kolom Anda. Sangat menarik untuk dicatat bahwa urutan pernyataan yang dikembalikan belum dibalik dan jika Anda membuat kueri ini sebagai tabel, kedua kolom akan menjadi varchar2
.
Saat memutuskan tipe data kolom dalam kueri pemilihan, Oracle mengambil tipe data pertama yang diketahui dan kemudian menggunakannya untuk menghitung tipe data keseluruhan. Inilah sebabnya mengapa pertanyaan di mana select
pertama adalah null jika barisnya dibalik.
Kueri pertama Anda berhasil karena pilihan pertama, select ename,to_number(null) from emp
, "menggambarkan" seperti apa set hasil itu nantinya. |varchar2|null|
. Kueri kedua kemudian menambahkan, |varchar2|varchar2|
, yang tidak menyebabkan masalah.
Kueri kedua Anda gagal karena yang pertama pilih select ename,to_number(null) from emp
"menggambarkan" hasil yang ditetapkan sebagai varchar2, null
. Namun, Anda kemudian mencoba menambahkan angka nol dan varchar2 di union
.
Lompatan keyakinan di sini adalah bahwa Oracle memutuskan bahwa to_number(null)
adalah angka sebelumnya ke union
dan tidak mengevaluasinya untuk "null-ness" sampai setelahnya. Saya tidak benar-benar tahu bagaimana menguji apakah ini benar-benar terjadi karena Anda tidak dapat membuat objek dengan null
kolom dan seperti yang Anda perhatikan, Anda juga tidak dapat memilihnya.
Karena saya tidak dapat membuktikan sesuatu yang dilarang Oracle, saya akan mencoba untuk bukti empiris. Pertimbangkan hasil (atau kesalahan) dari kueri berikut.
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
Mereka tampaknya menunjukkan bahwa to_char
dan to_number
, tidak peduli apakah itu dilakukan pada null secara implisit mendefinisikan tipe data yang kemudian dievaluasi untuk kesesuaiannya dalam union
, sebelum evaluasi mereka untuk "null-ness"
Penjelasan ini juga akan mencakup coalesce
masalah sebagai to_number(null)
adalah angka sebelum itu nol.