Puoi cambiare il tuo codice per fare:
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;
Ciò verifica che la colonna sia nulla o corrisponde al val
fornito e utilizza una variabile di collegamento per fornire il valore da controllare per ridurre un po' l'analisi.
Tuttavia, questo si basa ancora sulla conversione implicita, quindi se avessi un valore di data nella tabella, ad esempio, faresti affidamento sulle impostazioni NLS per convertirlo in modo che corrisponda al tipo di colonna della tabella di destinazione.
Puoi usare all_tab_columns
view per trovare il tipo di dati della colonna di destinazione ed eseguire la conversione esplicita di val
a quel tipo prima del binding. Un approccio più complesso ma forse più robusto sarebbe quello di utilizzare dbms_sql
per l'SQL dinamico interno invece di execute immediate
.
Tuttavia, la query esterna non sembra dover essere dinamica, potresti farlo:
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;
/