Silakan pertimbangkan skrip berikut:
create or replace function f(p_limit in integer) return integer as
begin
set_global_context ('limit', p_limit);
return p_limit;
end;
/
create view v as
select level as val from dual connect by level<=sys_context('global_context','limit');
select f(2), v.* from v;
/*
F(2) VAL
---------------------- ----------------------
2 1
2 2
*/
select f(4), v.* from v;
/*
F(4) VAL
---------------------- ----------------------
4 1
4 2
4 3
4 4
*/
Dapatkah saya mengandalkan f(x)
dieksekusi sebelum konteksnya dibaca di dalam tampilan, seperti yang telah dalam pengujian ini dijalankan pada 10.2?
SELECT stuff FROM dbo.FuncReturningTable(param)
atau serupa. Oracle mungkin memiliki fungsi yang setara. Meskipun jika menggunakan ini pada set data besar saya akan berhati-hati untuk memantau kinerja: Saya tidak yakin seberapa cerah perencana kueri perlu membuat rencana yang efisien dari sintaksis seperti itu.Jawaban:
Tidak.
Jika Anda menulis ulang tampilan Anda dengan pemfilteran konteks terhadap klausa di mana (alih-alih terhubung dengan), Anda akan mendapatkan nilai yang ditetapkan sebelumnya untuk konteks:
Ketika klausa tempat dievaluasi sebelum kolom dipilih, nilai yang diteruskan ke fungsi tidak ditetapkan sampai setelah konteks dibaca. Lokasi panggilan sys_context dalam kueri Anda (pilih, di mana, kelompokkan, dll.) Akan memengaruhi tepat saat nilai ini ditetapkan.
sumber
Secara umum Anda tidak dapat dengan aman berasumsi tentang urutan di mana DBMS Anda akan melakukan hal-hal ketika mengevaluasi pernyataan SQL tunggal. Inilah sebabnya mengapa banyak DBMS tidak akan mengizinkan fungsi yang digunakan seperti itu memiliki efek samping (mis. MSSQL tidak akan mengizinkan fungsi untuk mengatur global / keadaan koneksi, yang Anda lakukan di sana, atau mengubah konten tabel). Serangkaian pernyataan harus dieksekusi dengan cara yang masuk akal dari satu langkah ke langkah berikutnya (yaitu dijalankan secara seri, atau sedemikian rupa sehingga Anda tidak tahu itu tidak), tetapi dalam satu pernyataan, perencana kueri memiliki pemerintahan bebas selama itu tidak memperkenalkan ambiguitas di mana ia belum ada (dalam contoh Anda ambiguitas sudah ada karena fungsi memiliki efek samping yang mempengaruhi tampilan).
Jika perencana kueri cukup cerdas untuk mendeteksi bahwa tampilan dipengaruhi oleh efek samping fungsi, apa yang akan dilakukannya jika Anda bergabung dalam tampilan lain yang menyebut fungsi tersebut berpotensi dengan nilai input yang berbeda? Ini bisa sangat cepat menjadi sangat berbulu - hal semacam ini adalah mengapa pada umumnya, dalam konteks pemrograman apa pun, fungsi seharusnya tidak memiliki efek di luar output mereka sendiri.
Dalam contoh khusus ini saya akan mengatakan bahwa tidak mungkin bahwa f (x) akan dipanggil pertama, karena itu adalah bagian "tampilan" dari pernyataan: hasil yang ditetapkan dari tampilan cenderung diambil sebelum fungsi apa pun dalam daftar kolom untuk kembali dievaluasi. Tentu saja ini akan bervariasi tergantung pada DBMS yang digunakan: Saya bukan ahli Oracle dan hasil tes Anda menunjukkan bahwa fungsi tersebut tampaknya dipanggil pertama kali dalam hal ini. Tapi saya akan berhati-hati mengandalkan perintah eksekusi dalam pernyataan SQL tunggal semua sama - bahkan jika itu selalu bekerja seperti yang Anda harapkan saat ini mungkin tidak melakukannya dalam revisi di masa depan (kecuali jika secara resmi didokumentasikan di suatu tempat bahwa eksekusi akan selalu berjalan begini).
sumber
Dokumentasi hanya menjanjikan bahwa "Pengoptimal pertama-tama mengevaluasi ekspresi dan kondisi yang mengandung konstanta semaksimal mungkin." ( 10.2 , 11.2 ). Anda tidak dijamin bahwa itu akan mengevaluasi ekspresi tertentu terlebih dahulu, atau bahwa itu tidak akan mengubah urutan itu dari waktu ke waktu (patchlevel baru dalam rilis yang sama?).
sumber