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的主要内容,如果未能解决你的问题,请参考以下文章