使用 FORALL 和 RETURNING 插入表时如何获取 ROWID

Posted

技术标签:

【中文标题】使用 FORALL 和 RETURNING 插入表时如何获取 ROWID【英文标题】:How to get ROWID when inserting into table using FORALL and RETURNING 【发布时间】:2017-09-12 07:43:59 【问题描述】:

我想使用 FORALL INSERT 语句(批量插入)中的 RETURNING 子句将插入记录的 ROWID 返回到 pl/sql 记录表(关联记录数组)中。 我相信,这个问题在于同时使用 FORALL 和 BULK COLLECT 中的记录表。

看例子:

CREATE TABLE test2 (num NUMBER);
set serveroutput on

DECLARE
  TYPE r_rec IS RECORD (num NUMBER, row_id ROWID);
--  TYPE t_rid IS TABLE OF rowid INDEX BY BINARY_INTEGER;
  TYPE t_tab IS TABLE OF r_rec INDEX BY BINARY_INTEGER;
  v_tab     t_tab;
  --v_rid     t_rid;
BEGIN
  v_tab(1).num := 1.11;
  v_tab(2).num := 2.22;
  v_tab(3).num := 3.33;
  --
  FORALL i IN v_tab.first..v_tab.last
    INSERT INTO test2 (num)
    VALUES (v_tab(i).num)
    RETURNING rowid BULK COLLECT INTO v_tab(i).row_id
  ;
  FOR i IN v_tab.first..v_tab.last
  LOOP
     dbms_output.put_line('num/rowid : ' || v_tab(i).num || '/' || v_tab(i).row_id);
  END LOOP;
END;
/

引发错误:PLS-00437: FORALL bulk index cannot be used in RETURNING clause 这里哪里有问题?我是否需要另一个 PL/SQL 表来返回 ROWID?

【问题讨论】:

好吧,rowid 是在插入记录时分配给该记录的。可以在 RETURNING 子句中获取它。我只需要将它放回 pl/sql 表+记录中。请参阅示例。我的问题与此有关。 【参考方案1】:

我是否需要另一个 PL/SQL 表来返回 ROWID?

是的 ..您可以尝试如下:您需要另一个集合来保存 rowids 的返回,因为“FORALL 批量索引不能用于 RETURNING 子句”

DECLARE
  TYPE r_rec IS RECORD (num NUMBER, row_id ROWID);

  TYPE t_tab IS TABLE OF r_rec INDEX BY BINARY_INTEGER;
  v_tab     t_tab;

  TYPE r_rw IS TABLE OF ROWID index by pls_integer;

  v_rw r_rw;

BEGIN
  v_tab(1).num := 1.11;

  v_tab(2).num := 2.22;

  v_tab(3).num := 3.33;

  --
  FORALL i IN v_tab.first..v_tab.last
    INSERT INTO test2 (num)
    VALUES (v_tab(i).num)
    RETURNING rowid BULK COLLECT INTO v_rw;

  FOR i IN v_tab.first..v_tab.last
  LOOP
     dbms_output.put_line('num/rowid : ' || v_tab(i).num || '/' ||v_rw(i));
  END LOOP;

END;
/

【讨论】:

不幸的是,这是一个有点脆弱的解决方案,因为不能确保v_rw 的索引与v_tab 的索引相同。但这似乎是唯一可能的解决方案。 @LiborStefek。这是在v_tab 的循环中运行的,因此您可以确定使用的索引是正确的。请参阅此dba-oracle.com/plsql/t_plsql_dml.htm。此外,如果这回答了您的查询,您可以通过接受解决方案来关闭问题。 尝试将v_tab(1).num := 1.11; 更改为v_tab(4).num := 1.11;i 的索引是 2,3,4,但 v_rw 的索引是 1,2,3。这就是我所说的“脆弱”。我需要考虑到这一点。 那么v_tab(1).num 的值是多少?你想制作稀疏集合还是什么?然后它会抛出错误。 Indices i are 2,3,4, - 没有 Oracle 认为 FORALL i 索引不是您的集合索引。另外,当你做这样的事情时,它会抛出错误。试试看。

以上是关于使用 FORALL 和 RETURNING 插入表时如何获取 ROWID的主要内容,如果未能解决你的问题,请参考以下文章

BULK 收集和 FORALL 两次插入数据

我试图从 sys_refcursor 获取 bulkcollect 记录并尝试使用 forall 插入另一个表,但它抛出了一条错误消息

Oracle pl/sql forall:如何计算表空间已满(1654)错误的实际插入行数

如何在 APEX 应用程序的 csv 文件的批量数据插入中使用 forall 语句

尝试使用 RETURNING 和更新/插入从 plpgsql 函数返回时出错

sql Postgres在插入时使用RETURNING进行分区