SQL%ROWCOUNT 未提供动态 SQL Oracle 中的 BULK COLLECT 和 FORALL PL/SQL 所需的结果

SQL%ROWCOUNT is not providing desired outcome with dynamic SQL Having BULK COLLECT and FORALL in Oracle PL/SQL

SQL%ROWCOUNT 返回 运行 考虑的计数 (10),而不是更新记录的确切数量。期望 SQL%ROWCOUNT 应该提供更新的实际记录数。请建议我如何完成任务。

触发动态的代码SQL

FORALL indx IN 1 .. l_account_data.COUNT  --assume 10 as count
  SAVE EXCEPTIONS
  EXECUTE IMMEDIATE dynamic_sql_query USING l_account_data (indx);
  DBMS_OUTPUT.put_line ('Successful UPDATE of '|| TO_CHAR (SQL%ROWCOUNT) || ' record');
  COMMIT;

dynamic_sql_query

BEGIN
   
   SELECT clmn_x, clmn_y
     BULK COLLECT INTO l_subscr_data
     FROM table_x e, table_y c
    WHERE c.ref_id = :account_no AND e.account_no = c.account_no;


   FORALL indx IN 1 .. l_subscr_data.COUNT
      UPDATE table_z ciem                --this update will update multiple records for each account
         SET ciem.ext_id = ciem.sub_no || ROWID
       WHERE ciem.sub_no = l_subscr_data (indx).clmn_x
             AND ciem.subscr_no_resets =   l_subscr_data (indx).clmn_y
             AND ciem.status  IN (1,2);
             
END;

您的外部 execute immediate 调用不知道动态 SQL 内部发生了什么;它不知道自己在做什么,也不知道它可能影响或不影响多少行。

要获得准确的计数,您需要修改动态语句以添加如下内容:

FOR indx IN 1 .. l_subscr_data.COUNT LOOP
   :total_count := :total_count + coalesce(SQL%BULK_ROWCOUNT(indx), 0);
END LOOP;

并将您的外部调用更改为 (a) 传递一个额外的 IN OUT 绑定变量来跟踪总计数,并且 (b) 使用 FOR 循环而不是 FORALL,因为这似乎只在第一个之后保留值动态调用(不确定是否已记录或错误)。所以像:

...
l_total_count number := 0;
...
FOR indx IN 1 .. l_account_data.COUNT LOOP
   EXECUTE IMMEDIATE dynamic_sql_query
      USING l_account_data (indx), in out l_total_count;
END LOOP;
DBMS_OUTPUT.put_line ('Successful UPDATE of '|| TO_CHAR (l_total_count) || ' record');

db<>fiddle demo 数据 made-up。