Bạn có thể thay đổi mã của mình để thực hiện:
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;
Điều đó kiểm tra xem cột có rỗng không hoặc khớp với val
được cung cấp và sử dụng một biến liên kết để cung cấp giá trị cần kiểm tra để cắt giảm phân tích cú pháp một chút.
Tuy nhiên, điều này vẫn dựa vào chuyển đổi ngầm định, vì vậy, nếu bạn có một giá trị ngày trong bảng, chẳng hạn, bạn sẽ dựa vào cài đặt NLS của mình để chuyển đổi nó cho phù hợp với loại cột của bảng mục tiêu.
Bạn có thể sử dụng all_tab_columns
xem để tìm kiểu dữ liệu của cột mục tiêu và thực hiện chuyển đổi rõ ràng val
vào loại đó trước khi ràng buộc. Một cách tiếp cận liên quan hơn nhưng có thể mạnh mẽ hơn sẽ là sử dụng dbms_sql
cho SQL động bên trong thay vì execute immediate
.
Tuy nhiên, truy vấn bên ngoài dường như không cần phải động, bạn phải làm như sau:
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;
/