使用INSERT替换RETURNING ... SELECT

时间:2018-03-09 14:01:03

标签: sql oracle sql-insert insert-select sql-returning

这种情况涉及通过复制另一个表中的某些列并将生成的密钥从此插入中返回来插入表中。使用Oracle数据库。

这基本上是本能的结果来写这个查询。

INSERT INTO TBL_XXX
SELECT COLA, COLB, COLC FROM TBL_YYY
RETURNING COLA INTO COL_RES

由于某些正当理由,不允许这样做。

有替代方案吗?

1 个答案:

答案 0 :(得分:4)

您正在使用insert into ... select from构造。因此,您的语句可能会插入多行,这意味着您的RETURNING子句将返回多行。因此,您需要使用BULK COLLECT语法填充新密钥的集合

所以我们尝试这样的事情......

declare
    /* NB: define this collection using the appropriate name  */
    type new_keys is table of table_xxx.cola%type;
    col_res new_keys;
begin
    INSERT INTO TBL_XXX
    SELECT COLA * 10, COLB, COLC FROM TBL_YYY
    RETURNING table_xxx.COLA bulk collect INTO COL_RES;
end;
/

......只是为了得到:

  

ORA-06550:第8行,第15栏:
  PL / SQL:ORA-00933:SQL命令未正确结束

那太糟糕了。

不幸的是,虽然RETURNING BULK COLLECT INTO适用于更新和删除,但它不适用于插入(或合并到那里)。我确信在Oracle内核的内部架构中存在非常合理的原因,但这应该有效,而且它并不是最烦人的。

无论如何,正如@PonderStibbons指出的那样有一个解决方法:FORALL构造。

declare
    type new_rows is table of tbl_xxx%rowtype;
    rec_xxx new_rows;
    type new_keys is table of tbl_xxx.cola%type;
    col_xxx new_keys;
begin
    select cola * 10, colb, colc 
    bulk collect into rec_xxx
    from tbl_yyy;

    forall idx in 1 .. rec_xxx.count()
        insert into tbl_xxx
        values rec_xxx(idx)
        returning tbl_xxx.cola bulk collect into col_xxx
    ;

    for idx in 1 .. rec_xxx.count() loop
        dbms_output.put_line('tbl_xxx.cola = ' || col_xxx(idx));
   end loop;
end;
/

这是a LiveSQL demo (free OTN login required)