为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】:
DM Database Server 6 4 V8
DB Version: 0x7000c
03134284094-20231011-204277-20067
【操作系统】:Kylin Linux Advanced Server V10 (Lance)
【CPU】:x84_64
【问题描述】*:原基于MySQL的系统,要适配达梦数据库,在使用官方迁移工具后原MySQL中的AUTO_INCREMENT列被转换成了达梦中设置为IDENTITY关键字的列。后来依据网络上的教程在Mybatis中使用了如下模板进行数据插入后主键值的获取
<selectKey resultType="long" keyProperty="id" order="AFTER">
<choose>
<when test="_databaseId == 'mysql'">
SELECT LAST_INSERT_ID()
</when>
<when test="_databaseId == 'dm8'">
SELECT @@IDENTITY
</when>
</choose>
</selectKey>
但最近,使用上述方法获取id的方式获取到的值明显小于实际上的最后一个主键值上百位的数值,这是什么原因导致的?应该如何修复,或者说应该使用SELECT @@IDENTITY
以外的方式?
我在社区里看到一般使用IDENT_CURRENT关键字获取自增主键值,达梦同样支持的AUTO_INCREMENT的列同样支持LAST_INSERT_ID。
此外SCOPE_IDENTITY
以及.NEXTVAL
(Mybatis-plus用的是这个,但必须手动创建序列?)也具有类似的功能,上面几种方式能做到像MySQL中"你可以生成一个序号,接着在同一个会话连接里调用LAST_INSERT_ID()来检索它。即使其他客户在此期间生成了它们自己的序号值,也不会出现任何问题。"这样的效果吗?对于IDENTITY关键字+Mybatis那个是最好的方法?
以下为错误展示的具体场景
与技术专家直接交流后发现是触发器的问题,关闭触发器后

SELECT @@IDENTITY
查询正确触发器定义
create or replace trigger "TEST"."ABI_TRIGGER" after INSERT or DELETE or UPDATE of "ID","ABI_CODE","BYTE_CODES" on "TEST"."ABI" referencing OLD ROW AS "OLD" NEW ROW AS "NEW" for each row BEGIN IF INSERTING THEN INSERT INTO TARGET.ABI VALUES(new.abi_code); END IF; IF UPDATING THEN update TARGET.ABI set abi_code = new.abi_code where id = new.id; END IF; IF DELETING THEN delete from TARGET.ABI where id = old.id; END IF; END;
触发器源表定义
CREATE TABLE "TEST"."ABI" ( "ID" BIGINT IDENTITY(120891, 1) NOT NULL, "ABI_CODE" BLOB, "BYTE_CODES" BLOB, NOT CLUSTER PRIMARY KEY("ID")) STORAGE(ON "MAIN", CLUSTERBTR) ;
触发器目标表定义
CREATE TABLE "TARGET"."ABI" ( "ID" BIGINT IDENTITY(120888, 1) NOT NULL, "ABI_CODE" BLOB, NOT CLUSTER PRIMARY KEY("ID")) STORAGE(ON "MAIN", CLUSTERBTR) ; 这个是目标表TREEGRAPH_DCPS.ABI 的定义
结论
select @@IDENTITY获取到了触发器执行后目标表的标识值

解决方法
1.用SCOPE_IDENTITY()替换@@IDENTITY
2.优化触发器,将id一并插入
尾声
至于这个问题是否是@@IDENTITY的bug就看技术人员的了,可能就是特性。最后根据上面那张图,还是建议各位使用select SCOPE_IDENTITY();