Ini tampaknya merupakan persyaratan yang sangat aneh, dan yang akan sulit untuk diselesaikan dengan cara yang kuat. STMT_OR_VALUE adalah perwujudan dari anti-pola Satu Kolom Dua Penggunaan. Selanjutnya, menyelesaikan STMT_OR_VALUE membutuhkan logika kontrol aliran dan penggunaan SQL dinamis. Akibatnya itu tidak bisa menjadi solusi SQL murni:Anda perlu menggunakan PL/SQL untuk merakit dan menjalankan kueri dinamis.
Berikut adalah bukti konsep untuk solusi. Saya telah memilih fungsi yang dapat Anda panggil dari SQL. Itu tergantung pada satu asumsi:setiap string kueri yang Anda masukkan ke TEST1.STMT_OR_VALUE memiliki proyeksi kolom numerik tunggal dan setiap string nilai adalah CSV data numerik saja . Dengan ketentuan ini, mudah untuk membuat fungsi yang menjalankan kueri dinamis atau menandai string menjadi serangkaian angka; keduanya dikumpulkan secara massal ke dalam tabel bersarang:
create or replace function get_ids (p_name in test1.name%type)
return sys.odcinumberlist
is
l_rec test1%rowtype;
return_value sys.odcinumberlist;
begin
select * into l_rec
from test1
where name = p_name;
if l_rec.type = 'SQL_QUERY' then
-- execute a query
execute immediate l_rec.stmt_or_value
bulk collect into return_value;
else
-- tokenize a string
select xmltab.tkn
bulk collect into return_value
from ( select l_rec.stmt_or_value from dual) t
, xmltable( 'for $text in ora:tokenize($in, ",") return $text'
passing stmt_or_value as "in"
columns tkn number path '.'
) xmltab;
end if;
return return_value;
end;
/
Perhatikan bahwa ada lebih dari satu cara untuk mengeksekusi pernyataan SQL dinamis dan banyak cara untuk menandai CSV menjadi serangkaian angka. Keputusan saya bersifat arbitrer:silakan ganti metode pilihan Anda di sini.
Fungsi ini dapat dipanggil dengan table()
hubungi:
select *
from data
where id in ( select * from table(get_ids('first'))) -- execute query
or id in ( select * from table(get_ids('second'))) -- get string of values
/
Manfaat besar dari pendekatan ini adalah merangkum logika seputar evaluasi STMT_OR_VALUE dan menyembunyikan penggunaan SQL Dinamis. Akibatnya mudah untuk menggunakannya dalam pernyataan SQL apa pun sambil mempertahankan keterbacaan, atau untuk menambahkan mekanisme lebih lanjut untuk menghasilkan satu set ID.
Namun, solusi ini rapuh. Ini hanya akan berfungsi jika nilai dalam test1
meja mematuhi aturan. Artinya, tidak hanya harus dapat dikonversi ke aliran nomor tunggal tetapi pernyataan SQL harus valid dan dapat dieksekusi oleh EXECUTE IMMEDIATE. Misalnya, tanda titik koma di data sampel pertanyaan tidak valid dan akan menyebabkan EXECUTE IMMEDIATE terlempar. SQL dinamis paling sulit karena mengubah kesalahan kompilasi menjadi kesalahan runtime.