Você pode alterar seu código para fazer:
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;
Isso verifica se a coluna é nula ou corresponde ao
val
fornecido , e usa uma variável de ligação para fornecer o valor a ser verificado para reduzir um pouco a análise. No entanto, isso ainda depende da conversão implícita, portanto, se você tivesse um valor de data na tabela, por exemplo, estaria confiando em suas configurações de NLS para convertê-lo para corresponder ao tipo de coluna da tabela de destino.
Você pode usar as
all_tab_columns
view para encontrar o tipo de dados da coluna de destino e fazer a conversão explícita do val
para esse tipo antes de vincular. Uma abordagem mais complexa, mas possivelmente mais robusta, seria usar dbms_sql
para o SQL dinâmico interno em vez de execute immediate
. A consulta externa não parece precisar ser dinâmica, você poderia fazer:
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;
/