KingbaseES 实现 MySQL 函数 last_insert_id

发布时间 2023-05-09 19:41:51作者: KINGBASE研究院

用户从mysql迁移到金仓数据库过程中,应用中使用了mysql函数last_insert_id()来获取最近insert的那行记录的自增字段值。
mysql文档中关于函数的说明和例子:
LAST_INSERT_ID()
如果没有参数,则LAST_INSERT_ID()返回一个BIGINT UNSIGNED(64位)值,表示AUTO_INCREMENT由于最近执行的INSERT语句而成功为列添加的第一个自动生成的值。LAST_INSERT_ID()如果没有成功插入行,则值保持不变(如果连接尚未成功INSERT,则返回0 )。

mysql> CREATE TABLE t (
       id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
       name VARCHAR(10) NOT NULL
       );

mysql> INSERT INTO t VALUES (NULL, 'Bob');

mysql> SELECT * FROM t;
+----+------+
| id | name |
+----+------+
|  1 | Bob  |
+----+------+

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+

mysql> INSERT INTO t VALUES
       (NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');

mysql> SELECT * FROM t;
+----+------+
| id | name |
+----+------+
|  1 | Bob  |
|  2 | Mary |
|  3 | Jane |
|  4 | Lisa |
+----+------+

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                2 |
+------------------+

KingbaseES中序列相关的函数有以下几个:

函数名称 说明
currval(regclass) 返回最近一次用nextval获取的指定序列的值
nextval(regclass) 递增序列并返回新值
setval(regclass,bigint)
setval(regclass,bigint,boolean)
设置序列的当前值
lastval() 返回最近一次用nextval获取的任何序列的值
[kbc7@singlekbdb zip]$ ksql -Usystem -d test -p 7788
ksql (V8.0)
输入 "help" 来获取帮助信息.

test=# select lastval;
错误:  在这个会话中还没有定义lastval

test=# create table t(id serial,name varchar);
CREATE TABLE
test=# insert into t(name) values ('a');
INSERT 0 1
test=# select lastval;
 lastval
---------
       1
(1 行记录)

test=# insert into t(name) values ('b'),('c'),('d');
INSERT 0 3
test=# select * from t;
 id | name
----+------
  1 | a
  2 | b
  3 | c
  4 | d
(4 行记录)

test=# select lastval;
 lastval
---------
       4
(1 行记录)

从函数功能看lastval结果最接近LAST_INSERT_ID,但是存在一些差别。
1.新会话连接直接调用lastval函数,会返回一个错误。错误: 在这个会话中还没有定义lastval。mysql 返回 0 。
2.KingbaseES会话中一次插入多条数据,lastval返回的是最后一条数据的值,mysql返回的是第一条数据的值(见上面例子)。 从结果看KingbaseES的返回值更符合实际情况。

在KingbaseES中自定义函数LAST_INSERT_ID函数时考虑通过异常捕获来实现初始连接返回0。

CREATE OR REPLACE FUNCTION last_insert_id() RETURNS bigint AS $$
begin
return pg_catalog.lastval();
exception when others then
 return 0;
end
$$ LANGUAGE plpgsql;

CREATE FUNCTION
test=# select last_insert_id;
 last_insert_id
----------------
              0
(1 行记录)