Oracle中如何获取添加行的id

Posted

技术标签:

【中文标题】Oracle中如何获取添加行的id【英文标题】:How to get the id of the added row in Oracle 【发布时间】:2011-03-28 23:07:46 【问题描述】:

我需要将一个脚本从 tsql 翻译成 plsql,类似于:

声明@temp_id int 插入表 (col1, col2) 值 (1, 2) SET @temp_id = @@identity

但是,我很难找到类似于全局变量 @@identity 的东西

Oracle 专家吗?

【问题讨论】:

Oracle: how to create an identity column?的可能重复 顺便说一句,在 SQL Server @@identity 上,如果存在触发插入其他表的触发器,则可能无法给出正确答案。最佳实践建议改用scope_identity() 【参考方案1】:

假设您有some kind of trigger to populate the primary key column with a sequence,并且您想获得分配的值...

INSERT INTO Table (col1, col2) VALUES (1, 2) 
RETURNING pk_col INTO temp_id
/

请注意,RETURNING 语法仅适用于单行插入。

【讨论】:

【参考方案2】:

Michael Pakhantsov 的答案只能在单用户单任务环境中使用。 insert 和 select 语句是独立的语句! 在多用户多进程环境中会发生什么?

Process 1 insert
Process 2 insert
Process 2 select returns the is the id by process 2 insert
Process 1 select returns the is the id by process 2 insert NOT the process 1 insert

永远不要这样编程,甚至不要考虑它。 你需要一个原子操作,这意味着它不会受到任务切换的影响。

APC 的答案是:

create table FOO (
  id number primary key,
  name varchar2(100)    
);

create sequence FOO_seq;

create or replace trigger FOO_trg
before insert on FOO
for each row
begin
  select FOO_seq.nextval into :new.id from dual;
  dbms_output.put_line('inside trigger '||:new.id||' '||:new.name);
end;
/

declare
  temp_id number:=10;
begin  
  INSERT INTO FOO (id, name) VALUES (null, 'Vicky') RETURNING id INTO temp_id;
  dbms_output.put_line(temp_id);
  rollback;
  INSERT INTO FOO (id, name) VALUES (null, 'Joël') RETURNING id INTO temp_id;
  dbms_output.put_line(temp_id);
  commit;
end;  
/

select * from FOO;

drop table FOO;
drop sequence FOO_seq;

它会输出:

table FOO created.
sequence FOO_SEQ created.
TRIGGER FOO_TRG compiled
anonymous block completed
    ID NAME
------ --------
     2 joël        


table FOO dropped.
sequence FOO_SEQ dropped.

dbms_output 将是:

inside trigger 1 Vicky
1
inside trigger 2 Joël
2

请记住,您一次只能使用它来插入一行:

insert all
  into foo(id,name) values(null,'Vicky')
  into foo(id,name) values(null,'Joël')
  SELECT null,'none'  FROM dual  RETURNING id INTO temp_id;

给出 PL/SQL: ORA-00933: SQL command not properly end 错误,省略 RETURNING id INTO temp_id。

在 Oracle 12 中,您可以使用标识列并获得类似于 SQLServer 和 mysql 的内容。

CREATE TABLE foo (
  id   NUMBER GENERATED ALWAYS AS IDENTITY,
  name VARCHAR2(30)
);
/

declare
  temp_id varchar2(100);
begin
  INSERT INTO foo(name) VALUES ('Vicky') RETURNING id||' '||name INTO temp_id;
  dbms_output.put_line(temp_id);
  INSERT INTO foo(name) VALUES ('Joël') RETURNING id||' '||name INTO temp_id;
  dbms_output.put_line(temp_id);
end;
/

drop table foo;
purge recyclebin;

dbms_output 将是:

1 Vicky
2 Joël

添加了一条注释: 当您使用身份创建表时,将生成系统生成的序列。 即使删除表后,此序列仍将继续存在! 即使是 sysdba 也不能删除这个序列! 在 drop table 语句之后,您需要 purge recyclebin 来删除它们。

【讨论】:

【参考方案3】:

您需要使用序列。 (http://psoug.org/reference/sequences.html)

SequenceName.NEXTVAL 下一个值,sequenceName.CURRVAL - 最近使用的值(如@@Identity)

INSERT INTO Table (Id, col1, col2) VALUES (Sequence.NEXTVAL, 1, 2);

SELECT sequence.CURRVAL INTO Temp_ID from dual;

【讨论】:

以上是关于Oracle中如何获取添加行的id的主要内容,如果未能解决你的问题,请参考以下文章

当向Oracle数据库中插入数据时,如何获取行ID

Oracle:如何获取刚刚插入的行的序列号?

如何获取 MySQL 中最后更新行的 ID?

如何在 MySQL 中获取多个插入行的 ID?

Oracle始终获取具有标识的插入行的ID [重复]

如何使用旧驱动程序获取 JDBC 中插入行的 ID?