如何获取插入到表中的最后一个ID?在MS SQL中有SCOPE_IDENTITY()。postgreSQL函数为最后插入的ID
请,不建议使用这样的事情:
select max(id) from table
如何获取插入到表中的最后一个ID?在MS SQL中有SCOPE_IDENTITY()。postgreSQL函数为最后插入的ID
请,不建议使用这样的事情:
select max(id) from table
(tl;dr
:GOTO选项3:与返回的INSERT)
回想一下,PostgreSQL中存在用于表没有“ID”的概念,只是序列(其通常但不一定用作替代默认值主键,与SERIAL伪类型)。
如果你有兴趣在获得新插入的行的ID,有几种方法:
选项1:CURRVAL(<sequence name>);
。
例如:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
序列必须是已知的,它是真正的任意名称;在这个例子中,我们假设表persons
有一个id
列,该列由SERIAL
伪类型创建。为了避免依赖于这个,感觉更干净,你可以改用pg_get_serial_sequence
:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
警告:currval()
只能在同一会话的INSERT
后工作(已经执行nextval()
),。
选项2:LASTVAL();
这类似于以前的,只是你并不需要指定序列名:它查找最近修改序列(总会话中,相同警告如上)。
两个CURRVAL
和LASTVAL
是完全并行的安全。序列在PG中的行为被设计为使得不同的会话不会发生干扰,因此不存在竞争条件的风险(如果另一个会话在INSERT和SELECT之间插入另一行,我仍然可以获得正确的值)。
但是他们确实有一个微妙的潜在问题。如果数据库有一些TRIGGER(或RULE),在插入到persons
表中时,会在其他表中插入一些额外的内容...然后LASTVAL
可能会给我们带来错误的值。如果额外的插入是在同一个persons
表中完成的,这个问题甚至可能发生在CURRVAL
(这通常不太常见,但风险仍然存在)。
方案3:INSERT
与RETURNING
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
这是最清洁,高效,安全的方式来获得的ID。它没有任何前面的风险。
缺点?几乎没有:您可能需要修改调用INSERT语句的方式(最糟糕的情况是,您的API或DB层可能不希望INSERT返回值);它不是标准的SQL(谁在乎);它可因为PostgreSQL 8.2(2006年12月...)
结论:如果你可以去选择3.在其他地方,更喜欢1
注:所有这些方法都是无用的,如果你打算获取最后全局插入的ID(不一定在您的会话中)。为此,您必须求助于select max(id) from table
(当然,这不会读取来自其他事务的未提交插入)。
LASTVAL()可能非常邪恶,以防将触发器/规则插入到其他表中。 – 2012-10-25 15:17:41
'SELECT max(id)'不幸的是,只要开始删除行,就不会完成这项工作。 – 2012-11-02 16:44:30
@ SimonA.Eugster为什么不呢? – leonbloy 2012-11-02 17:11:22
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用这个表“用户”以次列名“ID”
SELECT currval(pg_get_serial_sequence('users', 'id'));
请参阅INSERT声明的RETURNING子句。基本上,INSERT加倍作为查询,并返回插入的值。
您可以使用INSERT语句,返回条款,就像下面
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 nextval('my_seq_name'); // Returns next value
如果返回1(或任何对你的序列START_VALUE),然后将序列重置回原始值,通过假标志:
select setval('my_seq_name', 1, false);
否则,
select setval('my_seq_name', nextValue - 1, true);
这会将序列值恢复到原始状态,“setval”将返回您正在查找的序列值。
如果你只需要检索没有插入任何你可以用下面的例子
SELECT id FROM users ORDER BY id DESC LIMIT 1;
希望能帮最后插入的ID。
Op不要求这种类型的解决方案 – ModChowdhury 2016-05-21 15:13:24
Leonbloy's answer非常完整。我只会添加一个特殊情况,其中需要从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的OPTION 3的微小的变化:
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO [new_variable];
注意,有两成的条款。
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;
现在我们可以使用插入新的数据:因此,PL/pgSQL函数想被定义
SELECT new_client('Smith', 'John');
或
SELECT * FROM new_client('Smith', 'John');
而我们得到新创建的ID 。
new_client
integer
----------
1
对于谁需要获得所有数据记录的,你可以添加
returning *
到您的查询的末尾以获得包括ID的所有对象。
你为什么讨厌最大功能?我认为这很简单。有没有安全问题? – 2016-11-25 07:41:06
@ jeongmin.cha如果存在其他操作和更多插入操作(并发操作)之间存在问题,则表示max id已更改,除非并且直到明确地取锁并且不释放它 – rohanagarwal 2017-07-14 14:00:51