Du kan ändra din kod för att göra:
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 kontrollerar att kolumnen är null eller matchar det medföljande val
, och använder en bindningsvariabel för att tillhandahålla värdet som ska kontrolleras för att minska parsningen lite.
Detta förlitar sig dock fortfarande på implicit konvertering, så om du till exempel hade ett datumvärde i tabellen skulle du lita på att dina NLS-inställningar konverterar det så att det matchar kolumntypen för måltabellen.
Du kan använda all_tab_columns
visa för att hitta datatypen för målkolumnen och göra explicit konvertering av val
till den typen innan bindning. En mer involverad men möjligen mer robust metod skulle vara att använda dbms_sql
för den inre dynamiska SQL istället för execute immediate
.
Den yttre frågan verkar dock inte behöva vara dynamisk, du kan göra:
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;
/