Puedes cambiar tu código para hacer:
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;
Eso comprueba que la columna es nula o coincide con el val
suministrado y utiliza una variable de vinculación para proporcionar el valor a verificar para reducir un poco el análisis.
Sin embargo, esto todavía se basa en la conversión implícita, por lo que si tuviera un valor de fecha en la tabla, por ejemplo, estaría confiando en su configuración de NLS para convertirlo para que coincida con el tipo de columna de la tabla de destino.
Puede usar all_tab_columns
view para encontrar el tipo de datos de la columna de destino y realizar una conversión explícita del val
a ese tipo antes de enlazar. Un enfoque más complicado pero posiblemente más sólido sería usar dbms_sql
para el SQL dinámico interno en lugar de execute immediate
.
Sin embargo, la consulta externa no parece necesitar ser dinámica, podrías hacer:
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;
/