Vous pouvez modifier votre code pour :
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;
Cela vérifie que la colonne est nulle ou correspond au val
fourni , et utilise une variable de liaison pour fournir la valeur à vérifier afin de réduire un peu l'analyse.
Cependant, cela repose toujours sur une conversion implicite, donc si vous aviez une valeur de date dans la table, par exemple, vous vous fieriez à vos paramètres NLS pour la convertir afin qu'elle corresponde au type de colonne de la table cible.
Vous pouvez utiliser les all_tab_columns
vue pour trouver le type de données de la colonne cible et faire une conversion explicite de la val
à ce type avant la liaison. Une approche plus impliquée mais peut-être plus robuste consisterait à utiliser dbms_sql
pour le SQL dynamique interne au lieu de execute immediate
.
La requête externe ne semble pas avoir besoin d'être dynamique, vous pouvez le faire :
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;
/