Можете да промените кода си, за да направите:
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;
Това проверява дали колоната е нула или съвпада с предоставената val
и използва свързваща променлива, за да предостави стойността за проверка, за да намали малко парсинга.
Това обаче все още разчита на имплицитно преобразуване, така че ако сте имали стойност на дата в таблицата например, ще разчитате на вашите NLS настройки, за да я преобразувате, за да съответства на типа колона на целевата таблица.
Можете да използвате all_tab_columns
изглед, за да намерите типа данни на целевата колона и да направите изрично преобразуване на val
към този тип преди обвързване. По-ангажиращ, но вероятно по-стабилен подход би бил използването на dbms_sql
за вътрешния динамичен SQL вместо execute immediate
.
Външната заявка обаче изглежда не трябва да бъде динамична, можете да направите:
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;
/