Liquibase loadUpdateData在Derby数据库中仅执行Insert未触发更新
loadUpdateData Only Executing Inserts on Derby 我来帮你排查这个问题,结合你使用的Derby 10.12.1.1和Liquibase 3.5.1版本,大概率是这几个关键点导致loadUpdateData只执行Insert、不触发Update逻辑:
1. 未正确配置重复判断的主键/唯一键
loadUpdateData的核心逻辑是通过主键或唯一约束识别重复行,如果你的变更日志里没指定primaryKey属性,或者指定的列在Derby表中没有主键/唯一约束,Liquibase根本没法判断哪些行是重复的,自然只会执行Insert操作。
举个正确的配置示例:
<changeSet id="load_update_users" author="your_name"> <loadUpdateData tableName="users" file="users.csv" primaryKey="user_id"> <column name="user_id" type="INT"/> <column name="username" type="VARCHAR(50)"/> <column name="email" type="VARCHAR(100)"/> </loadUpdateData> </changeSet>
一定要确保primaryKey指定的列在Derby表中是主键,或者有唯一约束——这是触发Update的前提。
2. Derby与旧版Liquibase的MERGE语法兼容性问题
Liquibase的loadUpdateData内部是用MERGE语句实现的,但Derby对MERGE的语法支持有特定要求,而Liquibase 3.5.1是2017年的旧版本,可能存在对Derby MERGE语句生成的bug。
你可以尝试改用mergeData变更集来替代,手动指定数据(不用CSV),直接生成MERGE语句:
<changeSet id="merge_user_data" author="your_name"> <mergeData tableName="users"> <column name="user_id" valueNumeric="1"/> <column name="username" value="updated_john"/> <column name="email" value="john.updated@example.com"/> </mergeData> </changeSet>
这种方式绕开了CSV加载的逻辑,直接生成适配Derby的MERGE语句,大概率能触发更新操作。
3. CSV数据与数据库现有数据不匹配
仔细检查你CSV文件里的主键值,是否和数据库中已存在的主键完全一致——比如数据类型(整数和字符串的区别)、大小写、多余空格等,哪怕是细微的差异,Liquibase都会认为是新行,执行Insert而不是Update。
比如数据库里user_id是整数1,CSV里写成"1 "(末尾带空格),就会被判定为不同的主键值,导致插入新行。
4. 旧版Liquibase的已知bug
Liquibase 3.5.1确实存在一些与Derby兼容的已知问题,尤其是在处理loadUpdateData的时候。如果上面的方法都无效,最稳妥的方案是升级Liquibase到较新的稳定版本(比如4.x系列),新版本对Derby的支持更完善,能解决很多旧版本的兼容性问题。
内容的提问来源于stack exchange,提问作者Maevy

