次のようにコードを変更できます:
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;
これにより、列がnullであることを確認しますまたは 指定されたval
と一致します 、およびバインド変数を使用してチェックする値を指定し、解析を少し削減します。
ただし、これは依然として暗黙的な変換に依存しているため、たとえばテーブルに日付値がある場合は、NLS設定に依存して、ターゲットテーブルの列タイプに一致するように変換します。
all_tab_columns
を使用できます ビューを表示してターゲット列のデータ型を検索し、val
を明示的に変換します バインドする前にそのタイプに。より複雑ですが、おそらくより堅牢なアプローチは、dbms_sql
を使用することです。 execute immediate
の代わりに内部動的SQLの場合 。
ただし、外部クエリは動的である必要はないようですが、次のようにします。
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;
/