PLSQL Insert into with 子查询和返回子句

发布于 2024-10-22 03:07:30 字数 604 浏览 5 评论 0原文

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

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

我想插入带有子查询值的内容。 插入后我需要新生成的 id。

以下是 oracle 文档所说的内容:

插入语句

返回

好吧,我认为仅使用值子句是不可能的...... 还有其他选择吗?

I can't figure out the correct syntax for the following pseudo-sql:

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

I would like to insert something with the values of a subquery.
After inserting I need the new generated id.

Heres what oracle doc says:

Insert Statement

Returning Into

OK i think it is not possible only with the values clause...
Is there an alternative?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

轻拂→两袖风尘 2024-10-29 03:07:30

您不能使用 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)
如本文所述:

使用 insert..select 返回

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;
   /

You cannot use the RETURNING BULK COLLECT from an INSERT.
This methodology can work with updates and deletes howeveer:

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;

You can get it to work with a few extra steps (doing a FORALL INSERT utilizing TREAT)
as described in this article:

returning with insert..select

T

to utilize the example they create and apply it to test2 test table

 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;
   /
淡墨 2024-10-29 03:07:30

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

Unfortunately that's not possible. RETURNING is only available for INSERT...VALUES statements. See this Oracle forum thread for a discussion of this subject.

掩耳倾听 2024-10-29 03:07:30

你不能,但至少在 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; 

You can't, BUT at least in Oracle 19c, you can specify a SELECT subquery inside the VALUES clause and so use RETURNING! This can be a good workaround, even if you may have to repeat the WHERE clause for every field:

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; 
一梦浮鱼 2024-10-29 03:07:30

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

毕竟,如果您的插入查询创建了两行 - 它将把哪个返回值放入单个变量中?

编辑 - 事实证明这并不像我想象的那样工作......该死!

Because the insert is based on a select, Oracle is assuming that you are permitting a multiple-row insert with that syntax. In that case, look at the multiple row version of the returning clause document as it demonstrates that you need to use BULK COLLECT to retrieve the value from all inserted rows into a collection of results.

After all, if your insert query creates two rows - which returned value would it put into an single variable?

EDIT - Turns out this doesn't work as I had thought.... darn it!

坏尐絯 2024-10-29 03:07:30

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

您将需要找出其他方法来执行此操作,您可以使用 ROWID 来执行此操作 - 但这有其缺陷。

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

This isn't as easy as you may think, and certainly not as easy as it is using MySQL. Oracle doesn't keep track of the last inserts, in a way that you can ping back the result.

You will need to work out some other way of doing this, you can do it using ROWID - but this has its pitfalls.

This link discussed the issue: http://forums.oracle.com/forums/thread.jspa?threadID=352627

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文