Du kan ændre din kode til at gøre:
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;
Det kontrollerer, at kolonnen er nul eller matcher den medfølgende val
, og bruger en bind-variabel til at levere den værdi, der skal kontrolleres, for at reducere parsing en smule.
Dette afhænger dog stadig af implicit konvertering, så hvis du f.eks. havde en datoværdi i tabellen, ville du stole på, at dine NLS-indstillinger konverterede den til at matche kolonnetypen for måltabel.
Du kan bruge all_tab_columns
view for at finde datatypen for målkolonnen og udføre eksplicit konvertering af val
til den type før indbinding. En mere involveret, men muligvis mere robust tilgang ville være at bruge dbms_sql
for den indre dynamiske SQL i stedet for execute immediate
.
Den ydre forespørgsel ser dog ikke ud til at være dynamisk, du kan gøre:
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;
/