PLSQL Insert into with subquery和returning子句

PLSQL Insert into with subquery和returning子句,sql,oracle,plsql,insert,return-value,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 以下

我无法找出以下伪sql的正确语法:

INSERT INTO some_table
           (column1,
            column2)
     SELECT col1_value, 
            col2_value 
       FROM other_table
      WHERE ...       
  RETURNING id
       INTO local_var; 
我想插入具有子查询值的内容。 插入后,我需要新生成的id

以下是oracle doc所说的:

好的,我认为这是不可能的,只有价值条款。。。
有其他选择吗?

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

您需要找到其他方法来实现这一点,您可以使用ROWID来实现——但这有它的缺陷


此链接讨论了该问题:

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

毕竟,如果insert查询创建了两行,它会将哪个返回值放入单个变量中


编辑-结果这并不像我想的那样有效。。。。该死

不幸的是,这是不可能的。返回仅适用于INSERT…VALUES语句。有关此主题的讨论,请参阅。

您不能使用插入中返回的批量收集。 此方法可用于更新和删除,但是:

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;
您只需执行一些额外的步骤,即可使其正常工作 如本文所述:

T

为了利用这个示例,他们创建并将其应用于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;
   /

不能,但至少在Oracle 19c中,可以在VALUES子句中指定SELECT子查询,然后使用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; 

我试过了,但是我得到了一个ORA 009333。SQL命令在where之后未正确结束。收集类型是个好主意。正如Tony在回答中所说,批量收集不适用于INSERT,至少在10g及更早的版本中是如此。我不清楚这是否在11g中发生了变化。是的,我认为这有效,但似乎没有。很抱歉,这是个错误的建议。这与所问的问题无关-它不是关于识别任何会话插入的最后一行,而是关于从特定的INSERT语句返回一组值。这很酷!留给我的唯一问题是声明对象类型。无法在包中声明对象类型。。。