是否可以 return Insert as select 语句中的主键 - Oracle?

Is it possible to return the Primary Key on an Insert as select statement - Oracle?

所以我通常在使用触发器时获取新插入记录的主键如下。

insert into table1 (pk1, notes) values (null, "Tester") returning pk1 into v_item;

我正在尝试使用相同的概念,但使用 select 语句进行插入。例如:

insert into table1 (pk1, notes) select null, description from table2 where pk2 = 2 returning pk1 into v_item;

注意:
1. table1 上有一个触发器,它会在插入时自动创建一个 pk1。
2. 由于要插入的 table 的大小,我需要使用 select 插入。
3.插入基本上是记录的复制,所以一次只插入1条记录。

如果我可以提供更多信息,请告诉我。

我不相信你可以直接用 insert/select 做到这一点。但是,您可以使用 PL/SQL 和 FORALL 来完成。考虑到 table 大小的限制,您必须使用 l_limit 来平衡内存使用和性能。这是一个例子...

鉴于此 table 有 100 行:

create table t (
  c  number generated by default as identity,
  c2 number
);

insert into t (c2)
select rownum
from dual
connect by rownum <= 100;

你可以这样做:

declare

  cursor t_cur
  is
    select c2
    from t;

  type t_ntt is table of number;

  l_c2_vals_in t_ntt;
  l_c_vals_out t_ntt;
  l_limit      number := 10;

begin

  open t_cur;

  loop
    fetch t_cur bulk collect into l_c2_vals_in limit l_limit;

    forall i in indices of l_c2_vals_in
    insert into t (c2) values (l_c2_vals_in(i))
    returning c bulk collect into l_c_vals_out;

    -- You have access to the new ids here
    dbms_output.put_line(l_c_vals_out.count);

    exit when l_c2_vals_in.count < l_limit;
  end loop;

  close t_cur;

end;

你不能使用那个机制; as shown in the documentation 铁路图:

返回子句只允许在值版本中使用,不能在子查询版本中使用。

我将您的第二个限制(大约 'table size')解释为您必须处理的列数,可能是单个变量,而不是行数 - 我不知道看看这与这里有什么关系。不过,有一些方法可以避免每列有很多局部变量;你可以先 select 到行类型变量中:

declare
  v_item number;
  v_row table1%rowtype;
begin
  ...
  select null, description
  into v_row
  from table2 where pk2 = 2;

  insert into table1 values v_row returning pk1 into v_item;

  dbms_output.put_line(v_item);
  ...

或使用循环,如果您真的只有一行,这可能会使事情看起来比必要的更复杂:

declare
  v_item number;
begin
  ...
  for r in (
    select description
    from table2 where pk2 = 2
  )
  loop
    insert into table1 (notes) values (r.description) returning pk1 into v_item;
    dbms_output.put_line(v_item);
    ...
  end loop;
  ...

或与一个集合...正如@Dan 在我回答这个问题时发布的那样,所以我不会重复! - 虽然对于单行来说这可能有点矫枉过正或过于复杂。