在PostgreSQL中,我如何获得插入到表中的最后一个id?
在MS SQL中有SCOPE_IDENTITY()。
请不要建议我使用类似这样的东西:
select max(id) from table
在PostgreSQL中,我如何获得插入到表中的最后一个id?
在MS SQL中有SCOPE_IDENTITY()。
请不要建议我使用类似这样的东西:
select max(id) from table
(tl;dr
: 选择选项3: 带有RETURNING的INSERT)
回想一下,在postgresql中,表没有"id"的概念,只有序列(通常但不一定用作代理主键的默认值,使用SERIAL伪类型)。
如果您想获取新插入行的id,有几种方法:
选项1: CURRVAL(<序列名称>);
。
例如:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
序列的名称必须是已知的,实际上可以是任意的;在这个示例中,我们假设表persons
具有使用伪类型SERIAL
创建的id
列。为了避免依赖于此并且感觉更加清晰,您可以改用pg_get_serial_sequence
:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
注意:只有在同一会话中执行了nextval()
的INSERT
之后,currval()
才能起作用。
选项2:LASTVAL();
这与上一个选项类似,只是您不需要指定序列名称:它会查找最近修改的序列(始终在您的会话中,与上面相同的警告)。
CURRVAL
和LASTVAL
都是完全并发安全的。PG中序列的行为被设计成不会相互干扰,因此不存在竞争条件的风险(如果另一个会话在我的INSERT和SELECT之间插入了另一行,则我仍然可以获得正确的值)。persons
表中插入时,在其他表中进行一些额外的插入...那么LASTVAL
可能会给我们错误的值。如果额外的插入是在同一个persons
表中完成的,则甚至可能发生这种情况,即使这种情况较少见,但风险仍然存在。
RETURNING
的INSERT
。INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
SELECT max(id) FROM table
(当然,这将不会读取其他事务中未提交的插入记录)。SELECT max(id) FROM table
来代替上述三个选项之一,以获取刚刚由您的INSERT
语句生成的id,因为(除了性能问题)这不是并发安全的:在您的INSERT
和SELECT
之间,另一个会话可能已经插入了另一条记录。RETURNING id;
将数据插入到另一个表中的示例将非常有帮助! - Olivier Pons查看INSERT语句的RETURNING子句。基本上,INSERT语句作为查询,返回被插入的值。
insert into names (firstname, lastname) values ('john', 'smith') returning id;
,它将简单地输出id,就像直接运行select id from names where id=$lastid
一样。如果你想把返回值保存到一个变量中,则使用以下命令:insert into names (firstname, lastname) values ('john', 'smith') returning id into other_variable;
如果包含returning的语句是函数中的最后一个语句,那么被返回的id将作为整个函数的返回值。 - Alexander BirdLeonbloy的答案非常完整。我只想补充一个特殊情况,就是在PL/pgSQL函数内需要获取最后插入的值,而OPTION 3不完全适用的情况。
例如,如果我们有以下表:
CREATE TABLE person(
id serial,
lastname character varying (50),
firstname character varying (50),
CONSTRAINT person_pk PRIMARY KEY (id)
);
CREATE TABLE client (
id integer,
CONSTRAINT client_pk PRIMARY KEY (id),
CONSTRAINT fk_client_person FOREIGN KEY (id)
REFERENCES person (id) MATCH SIMPLE
);
如果我们需要插入客户记录,我们必须引用个人记录。但是假设我们想设计一个PL/pgSQL函数,它可以将新记录插入客户端,还要负责插入新的个人记录。为此,我们必须使用leonbloy选项3的轻微变化:
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO [new_variable];
请注意,这里有两个INTO子句。因此,PL/pgSQL函数的定义方式如下:
CREATE OR REPLACE FUNCTION new_client(lastn character varying, firstn character varying)
RETURNS integer AS
$BODY$
DECLARE
v_id integer;
BEGIN
-- Inserts the new person record and retrieves the last inserted id
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO v_id;
-- Inserts the new client and references the inserted person
INSERT INTO client(id) VALUES (v_id);
-- Return the new id so we can use it in a select clause or return the new id into the user application
RETURN v_id;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
现在我们可以使用以下方式插入新数据:
SELECT new_client('Smith', 'John');
SELECT * FROM new_client('Smith', 'John');
我们获得了新创建的ID。
new_client
integer
----------
1
RETURNING id INTO [new_variable]
的例子。 - Chris Kobrzak其他答案没有展示如何使用RETURNING
返回的值。以下是一个例子,演示如何将返回的值插入到另一张表中。
WITH inserted_id AS (
INSERT INTO tbl1 (col1)
VALUES ('foo') RETURNING id
)
INSERT INTO tbl2 (other_id)
VALUES ((select id from inserted_id));
你可以在INSERT语句中使用RETURNING子句,就像下面这样:
wgzhao=# create table foo(id int,name text);
CREATE TABLE
wgzhao=# insert into foo values(1,'wgzhao') returning id;
id
----
1
(1 row)
INSERT 0 1
wgzhao=# insert into foo values(3,'wgzhao') returning id;
id
----
3
(1 row)
INSERT 0 1
wgzhao=# create table bar(id serial,name text);
CREATE TABLE
wgzhao=# insert into bar(name) values('wgzhao') returning id;
id
----
1
(1 row)
INSERT 0 1
wgzhao=# insert into bar(name) values('wgzhao') returning id;
id
----
2
(1 row)
INSERT 0
SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))
你需要提供课程的表名和列名。这将用于当前会话/连接
http://www.postgresql.org/docs/8.3/static/functions-sequence.html看下面的例子:
CREATE TABLE users (
-- make the "id" column a primary key; this also creates
-- a UNIQUE constraint and a b+-tree index on the column
id SERIAL PRIMARY KEY,
name TEXT,
age INT4
);
INSERT INTO users (name, age) VALUES ('Mozart', 20);
要获取最后插入记录的 id,可以使用以下代码,其中表名为 "user",序列列(column)名称为 "id"。
SELECT currval(pg_get_serial_sequence('users', 'id'));
在插入查询之后,您可以使用 RETURNING id。
INSERT INTO distributors (id, name) VALUES (DEFAULT, 'ALI') RETURNING id;
并且结果:
id
----
1
在上面的例子中,id 是自增字段。对于那些需要获取所有数据记录的人,您可以添加
returning *
在您的查询末尾添加“全部对象(包括ID)”以获取所有对象。
insert into my_table(name) returning id into _my_id;