PLSQL插入子查询和返回子句(Oracle)

时间:2011-03-16 12:09:25

标签: sql oracle plsql insert return-value

我无法弄清楚以下伪sql的正确语法:

INSERT INTO some_table
           (column1,
            column2)
     SELECT col1_value, 
            col2_value 
       FROM other_table
      WHERE ...       
  RETURNING id
       INTO local_var; 

我想用子查询的值插入一些东西。 插入后我需要新生成的id。

这是oracle doc所说的:

Insert Statement

Returning Into

好吧我认为只有使用值条款才有可能...... 还有其他选择吗?

5 个答案:

答案 0 :(得分:15)

您无法使用INSERT中的RETURNING BULK COLLECT。 这种方法可以用于更新和删除操作:

create table test2(aa number)
/
insert into test2(aa)
      select level
        from dual
        connect by level<100
/        

set serveroutput on
declare 
     TYPE t_Numbers IS TABLE OF test2.aa%TYPE
        INDEX BY BINARY_INTEGER;
      v_Numbers t_Numbers;
      v_count number;
begin


update test2
  set aa = aa+1
returning aa bulk collect into v_Numbers;

    for v_count in 1..v_Numbers.count loop
        dbms_output.put_line('v_Numbers := ' || v_Numbers(v_count));
    end loop;

end;

你可以使用一些额外的步骤(使用TREAT进行FORALL INSERT) 如本文所述:

returning with insert..select

Ť

利用他们创建的示例并将其应用于test2测试表

 CREATE or replace TYPE ot AS OBJECT
    ( aa number);
/


CREATE TYPE ntt AS TABLE OF ot;
/

set serveroutput on
 DECLARE

       nt_passed_in ntt;
       nt_to_return ntt;

       FUNCTION pretend_parameter RETURN ntt IS
          nt ntt;
       BEGIN
          SELECT ot(level) BULK COLLECT INTO nt
         FROM   dual
         CONNECT BY level <= 5;
         RETURN nt;
      END pretend_parameter;

   BEGIN

      nt_passed_in := pretend_parameter();

      FORALL i IN 1 .. nt_passed_in.COUNT
         INSERT INTO test2(aa)
         VALUES
         ( TREAT(nt_passed_in(i) AS ot).aa
         )
         RETURNING ot(aa)
         BULK COLLECT INTO nt_to_return;

      FOR i IN 1 .. nt_to_return.COUNT LOOP
         DBMS_OUTPUT.PUT_LINE(
            'Sequence value = [' || TO_CHAR(nt_to_return(i).aa) || ']'
            );
      END LOOP;

   END;
   /

答案 1 :(得分:13)

不幸的是,这是不可能的。 RETURNING仅适用于INSERT ... VALUES语句。有关此主题的讨论,请参阅this Oracle forum thread

答案 2 :(得分:2)

您不能,但至少在 Oracle 19c 中,您可以在 SELECT 子句中指定 VALUES 子查询,因此使用 RETURNING!这可能是一个很好的解决方法,即使您可能必须为每个字段重复 WHERE 子句:

INSERT INTO some_table
           (column1,
            column2)
     VALUES((SELECT col1_value FROM other_table WHERE ...),
            (SELECT col2_value FROM other_table WHERE ...))
  RETURNING id
       INTO local_var; 

答案 3 :(得分:0)

由于插入基于select,因此Oracle假定您允许使用该语法进行多行插入。在这种情况下,请查看返回子句文档的多行版本,因为它演示了您需要使用BULK COLLECT将所有插入行中的值检索到结果集合中。

毕竟,如果你的插入查询创建了两行 - 返回的值是否会放入一个变量?

编辑 - 事实证明这并不像我原先想象的那样有效......坚持不懈!

答案 4 :(得分:-2)

这并不像你想象的那么容易,当然也不像使用MySQL那么容易。 Oracle不会以可以ping回结果的方式跟踪最后一次插入。

你需要尝试其他一些方法,你可以使用ROWID来做 - 但这有其缺陷。

此链接讨论了此问题:http://forums.oracle.com/forums/thread.jspa?threadID=352627