使用Liquibase导入CSV至PostgreSQL时,能否启用OVERRIDING SYSTEM VALUE?
场景与问题
你需要用Liquibase从CSV文件导入数据到PostgreSQL,但目标表的id列是GENERATED ALWAYS类型的自增列,直接用loadData会触发报错,提示需要用OVERRIDING SYSTEM VALUE来覆盖系统生成值。
当前使用的Liquibase配置:
- loadData: tableName: TABLE file: xyz.CSV
报错信息:
Caused by: org.postgresql.util.PSQLException: ERROR: cannot insert a non-DEFAULT value into column "id"
Detail: Column "id" is an identity column defined as GENERATED ALWAYS.
Hint: Use OVERRIDING SYSTEM VALUE to override.
可行解决方案
Liquibase原生的loadData标签默认不会生成带OVERRIDING SYSTEM VALUE的INSERT语句,你可以通过以下两种方式实现需求:
1. 改用原生PostgreSQL COPY命令(推荐)
直接在Liquibase中执行PostgreSQL的COPY语句,显式添加OVERRIDING SYSTEM VALUE:
- sql: sql: | COPY TABLE(id, col1, col2) FROM 'xyz.CSV' WITH (FORMAT csv, HEADER true) OVERRIDING SYSTEM VALUE;
注意:需要替换col1, col2为你的实际列名,同时确保CSV文件路径在PostgreSQL服务器可访问;如果是本地文件,可改用\copy命令(Liquibase中也可直接写对应的SQL)。
2. 临时修改列属性后用loadData导入
先把id列的生成规则临时改为GENERATED BY DEFAULT,完成导入后再改回GENERATED ALWAYS:
- sql: sql: ALTER TABLE TABLE ALTER COLUMN id SET GENERATED BY DEFAULT; - loadData: tableName: TABLE file: xyz.CSV - sql: sql: ALTER TABLE TABLE ALTER COLUMN id SET GENERATED ALWAYS;
这种方式不需要修改导入逻辑,但要保证操作在同一个事务中,避免中途失败导致列属性无法恢复。
内容的提问来源于stack exchange,提问作者BMcFadyen

