Sie können Ihren Code folgendermaßen ändern:
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;
Das prüft, ob die Spalte null oder ist stimmt mit dem angegebenen val
überein , und verwendet eine Bind-Variable, um den zu prüfenden Wert bereitzustellen, um das Parsen ein wenig zu reduzieren.
Dies ist jedoch immer noch auf implizite Konvertierung angewiesen. Wenn Sie also beispielsweise einen Datumswert in der Tabelle hätten, würden Sie sich auf Ihre NLS-Einstellungen verlassen, um ihn so zu konvertieren, dass er mit dem Spaltentyp der Zieltabelle übereinstimmt.
Sie können die all_tab_columns
verwenden view, um den Datentyp der Zielspalte zu finden und eine explizite Konvertierung von val
durchzuführen zu diesem Typ vor dem Binden. Ein komplizierterer, aber möglicherweise robusterer Ansatz wäre die Verwendung von dbms_sql
für das innere dynamische SQL statt execute immediate
.
Die äußere Abfrage scheint jedoch nicht dynamisch sein zu müssen, Sie könnten Folgendes tun:
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;
/