oracle 使用INSERT...SELECT代替RETURNING

r7xajy2e  于 2023-04-20  发布在  Oracle
关注(0)|答案(1)|浏览(210)

有这样一个场景,它涉及到通过从另一个表复制一些列来插入到一个表中,并返回从这个插入中生成的键。
这基本上是出于本能而写这个查询。

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

因为某些正当的理由而不被允许。
有没有别的办法?

pu82cl6c

pu82cl6c1#

您使用的是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命令未正确结束
那太糟了
不幸的是,虽然返回批量收集到工作与更新和删除它不工作与插入(或合并来)。我相信有非常健全的理由,在Oracle内核的内部架构,但这应该工作,它不最恼人的。
无论如何,正如@ PonderStibons指出的那样,有一个解决方案: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)

相关问题