You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Liquibase向PostgreSQL关联表导入CSV数据,如何关联父表ID?

解决PostgreSQL关联表通过Liquibase从CSV导入数据并关联父表ID的问题

核心思路是通过业务关联字段建立临时映射表,先将table1生成的ID与原CSV中的唯一业务标识绑定,再导入table2时通过该映射表匹配对应的父表ID,具体步骤如下:


1. 准备临时表与CSV导入

首先用Liquibase创建临时表,将CSV数据导入临时表(临时表无需ID字段,只需保留CSV中的业务字段,以及能关联table1和table2的唯一标识):

<changeSet id="import-temp-data" author="your-team">
    <!-- 创建table1临时表 -->
    <createTable tableName="table1_temp">
        <column name="field1" type="varchar"/>
        <column name="field2" type="varchar"/>
    </createTable>
    <!-- 导入table1的CSV数据 -->
    <loadData tableName="table1_temp" file="data/table1_data.csv" separator=",">
        <column name="field1"/>
        <column name="field2"/>
    </loadData>

    <!-- 创建table2临时表,需包含能关联table1的业务字段 -->
    <createTable tableName="table2_temp">
        <column name="field1" type="varchar"/> <!-- 和table1的field1对应 -->
        <column name="field2" type="varchar"/> <!-- 和table1的field2对应 -->
        <column name="field3" type="varchar"/>
    </createTable>
    <!-- 导入table2的CSV数据 -->
    <loadData tableName="table2_temp" file="data/table2_data.csv" separator=",">
        <column name="field1"/>
        <column name="field2"/>
        <column name="field3"/>
    </loadData>
</changeSet>

注:这里用field1+field2作为table1的唯一业务标识,你可以替换成CSV中实际存在的、能唯一区分table1记录的字段(比如单独的业务编码)。


2. 插入table1并建立ID映射表

通过INSERT ... RETURNING将table1生成的ID与原业务标识存入临时映射表,后续table2导入时用这个映射表匹配父ID:

<changeSet id="insert-table1-and-create-map" author="your-team">
    <sql>
        -- 创建临时映射表,存储业务标识与生成的table1 ID
        CREATE TEMP TABLE table1_id_map (
            origin_field1 varchar,
            origin_field2 varchar,
            table1_id numeric
        );

        -- 插入table1数据,同时将生成的ID和业务标识写入映射表
        INSERT INTO table1 (id, field1, field2)
        SELECT nextval('table1_sequence'), field1, field2 FROM table1_temp
        RETURNING field1, field2, id INTO table1_id_map;
    </sql>
</changeSet>

3. 插入table2并关联父表ID

通过JOIN映射表,将table2临时表中的业务标识对应到table1的ID,同时生成table2的自增ID:

<changeSet id="insert-table2-with-parent-id" author="your-team">
    <sql>
        INSERT INTO table2 (id, table1_id, field3)
        SELECT nextval('table2_sequence'), m.table1_id, t.field3
        FROM table2_temp t
        JOIN table1_id_map m 
            ON t.field1 = m.origin_field1 
            AND t.field2 = m.origin_field2;
    </sql>

    <!-- 清理临时表 -->
    <dropTable tableName="table1_temp"/>
    <dropTable tableName="table2_temp"/>
    <sql>DROP TABLE table1_id_map;</sql>
</changeSet>

关键注意事项

  • 确保你选择的业务关联字段(比如field1+field2)在table1中是唯一的,否则JOIN会出现重复匹配,导致table2数据错误。
  • 序列名称要和数据库中实际的序列名一致(比如你的table1序列如果是table1_id_seq,就替换nextval('table1_sequence')为nextval('table1_id_seq'))。
  • 临时表仅在当前会话有效,清理步骤可根据需求调整,不影响数据库永久结构。

内容的提问来源于stack exchange,提问作者sticky_elbows

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:15:05