Anda dapat mengubah kode Anda untuk melakukan:
v_lstmt := 'SELECT count(*) FROM userB.tableB WHERE id = '''||v_ret (i).id||''''
|| ' and ('||v_ret (i).col||' is null or '||v_ret (i).col||' = :val)';
EXECUTE IMMEDIATE v_lstmt INTO cDel using v_ret (i).val;
Itu memeriksa bahwa kolomnya nol atau cocok dengan val
. yang disediakan , dan menggunakan variabel bind untuk memberikan nilai yang akan diperiksa untuk mengurangi sedikit penguraian.
Namun ini masih bergantung pada konversi implisit, jadi jika Anda memiliki nilai tanggal dalam tabel misalnya, Anda akan mengandalkan setelan NLS Anda untuk mengonversinya agar sesuai dengan jenis kolom tabel target.
Anda dapat menggunakan all_tab_columns
tampilan untuk menemukan tipe data kolom target dan melakukan konversi eksplisit val
untuk jenis itu sebelum mengikat. Pendekatan yang lebih terlibat tetapi mungkin lebih kuat adalah dengan menggunakan dbms_sql
untuk SQL dinamis dalam alih-alih execute immediate
.
Kueri luar tampaknya tidak perlu dinamis, Anda dapat melakukannya:
declare
v_lstmt VARCHAR2(32000);
cDel number;
begin
for rec in (SELECT id, col, val FROM tableA) loop
v_lstmt := 'SELECT count(*) FROM tableB WHERE id = '''||rec.id||''''
|| ' and ('||rec.col||' is null or '||rec.col||' = :val)';
dbms_output.put_line(v_lstmt);
EXECUTE IMMEDIATE v_lstmt INTO cDel using rec.val;
If cDel > 0 Then
--some code
cDel := 0;
end if;
end loop;
end;
/