尝试在“插入”之后将 ID(由触发器/序列生成)返回给变量

Posted

技术标签:

【中文标题】尝试在“插入”之后将 ID(由触发器/序列生成)返回给变量【英文标题】:Trying to get a ID (generated by a trigger/sequence) returned to a variable after a 'Insert into' 【发布时间】:2018-06-19 18:41:15 【问题描述】:

我目前在 VALUE 表上设置了一个触发器(带有序列),每次将一行插入表中时,它都会自动生成一个新的 value_id。我正在尝试将新的 value_id(由触发器/序列生成)返回到变量中,以便稍后在 proc 中插入关系表中使用它。

但是,当我使用returning 语句时,Oracle 会返回错误。当我使用传统的插入时,代码似乎运行/编译得很好。

你知道我做错了什么吗?以下是我编写的代码的精简版:

insert into value 
  (value_id, 
   energy_product_id, 
   data_source_id, 
   unit_cd, 
   value_tx, 
   hr
  )
  select null, 
         energy_product_id, 
         data_source_id, 
         unit_cd, 
         value_tx
  from value
  returning value_id into v_value_id;

提前致谢

**编辑:** 下面是讨论过的更改的代码。但是它会出错:

insert into value 
  (value_id, 
   energy_product_id, 
   data_source_id, 
   unit_cd, 
   value_tx, 
   hr
  )
  select (select seq_sample.nextval from dual), 
         energy_product_id, 
         data_source_id, 
         unit_cd, 
         value_tx
  from value
  returning value_id into v_value_id;

【问题讨论】:

什么Oracle版本?请发一个minimal reproducible example你不是使用序列来生成值吗? 11.2.0 。我正在使用序列/触发器来生成值。但我需要将该值返回到一个变量中,以便稍后在另一个插入中使用它。 @OldProgrammer 我编辑了我的问题,感谢您的提醒。我是否按照该链接中的说明进行了正确的编辑? 所以不是触发器,而是在过程中获取 seq.nextval,然后您可以传递到多个插入中。 那将是不正确的,因为那样我会在我插入的值之后获得下一个值。我需要那个确切的值。例如:(1st Table) Value_ID (1) Value_TX(5) --- (2nd Table) Value_ID(1) Translation_ID(1) CREATE_DT(sysdate)。我需要'1' value_id 显示在两个表/插入中 【参考方案1】:

如果您的插入有 values (...) 子句,您似乎只能使用 returning into 子句,而不是在使用查询时。

您可以使用集合代替:

declare
  type t_rows is table of value_table%rowtype;
  v_rows t_rows;
begin
  select seq_sample.nextval, 
         energy_product_id, 
         data_source_id, 
         unit_cd, 
         value_tx, hr
  bulk collect into v_rows
  from value_table;

  forall i in 1..v_rows.count
    insert into value_table values v_rows(i);

  -- just as debug to see new ID values
  for i in 1..v_rows.count loop
    dbms_output.put_line(v_rows(i).value_id);
  end loop;
end;
/

如果您想保留触发器并且它会覆盖任何传入的值 - 这是正常的,但是这可能是一个例外情况 - 那么您可以使用第二个集合来取回 ID,带有批量收集返回子句:

declare
  type t_rows is table of value_table%rowtype;
  v_rows t_rows;
  type t_ids is table of number;
  v_ids t_ids;
begin
  select null, 
         energy_product_id, 
         data_source_id, 
         unit_cd, 
         value_tx, hr
  bulk collect into v_rows
  from value_table;

  forall i in 1..v_rows.count
    insert into value_table values v_rows(i)
    returning value_id bulk collect into v_ids;

  -- just as debug to see new ID values
  for i in 1..v_ids.count loop
    dbms_output.put_line(v_ids(i));
  end loop;
end;
/

ID 的索引应该与其他行数据的索引对应,因此您可以更新原始集合:

  for i in 1..v_rows.count loop
    v_rows(i).value_id := v_ids(i);
  end loop;

但我不确定这是否得到保证。它似乎应该,但我不记得看到它记录在案。

似乎应该有一个更直接的机制来实现这一点......

【讨论】:

【参考方案2】:

我最近发布了一个关于 Insert into return 的工作的问题,我相信 @APC 提供的答案将适用于你提到触发器将覆盖 https://***.com/a/50892580/7071906 分配值的情况,尝试类似

 declare
 select  CURSOR c1 IS
 SELECT 1 val,energy_product_id,data_source_id,unit_cd,value_tx from 
  value
 lrec c1%rowtype;
 ldata c1%rowtype;
id number;
 begin
fetch c1 into lrec

ldata.value_id := lrec.id;
ldata.energy_product_id := lrec.energy_product_id;
ldata.unit_cd := lrec.unit_cd;
ldata.value_tx :=  lrec.value_tx;

INSERT INTO my_table
VALUES ldata
RETURNING val1 INTO id;
end;

How does Oracle Insert Into work when order of values is not defined?

【讨论】:

谢谢,是的,我可以让传统的插入工作,但不能插入到 select from 中以返回任何内容......(如果有意义的话) 在这种情况下,这个***线程link已经为您的问题指出了解决方案,看起来正是您要问的) 啊...谢谢@prakriti,看来我要问的是不可能的:(

以上是关于尝试在“插入”之后将 ID(由触发器/序列生成)返回给变量的主要内容,如果未能解决你的问题,请参考以下文章

插入后选择Hibernate

mysql 在插入数据时,怎么样做到自动生成16位唯一的ID?

让Oracle触发ID而不是Hibernate的序列?

mongodb 插入之后怎样获取id

Oracle中触发器实现序列自增

用于在表上自动生成 ID 的序列和触发 PL/SQL 脚本