U kunt uw code wijzigen om te doen:
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;
Dat controleert of de kolom null is of komt overeen met de meegeleverde val
, en gebruikt een bindvariabele om de te controleren waarde op te geven om het parseren een beetje te verminderen.
Dit is echter nog steeds afhankelijk van impliciete conversie, dus als u bijvoorbeeld een datumwaarde in de tabel had, zou u vertrouwen op uw NLS-instellingen om deze te converteren zodat deze overeenkomt met het kolomtype van de doeltabel.
U kunt de all_tab_columns
. gebruiken bekijken om het gegevenstype van de doelkolom te vinden en expliciete conversie uit te voeren van de val
naar dat type alvorens te binden. Een meer betrokken maar mogelijk robuustere benadering zou zijn om dbms_sql
. te gebruiken voor de innerlijke dynamische SQL in plaats van execute immediate
.
De buitenste query lijkt echter niet dynamisch te hoeven zijn, dat kan wel:
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;
/