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

Liquibase:添加唯一约束前删除重复行

解决Liquibase新增唯一约束前清理重复行的问题

我来帮你搞定这个麻烦事!在生产环境不能修改旧changeset的情况下,咱们可以在新增唯一约束的changeset里先加入删除重复数据的逻辑,确保约束能顺利创建。

具体实现步骤

首先,你需要先清理表中的重复行,然后再添加唯一约束。这里假设你要给foo表的target_column列(替换成你的实际列名)添加唯一约束,下面是完整的changeset示例:

<changeSet id="123" author="me">
    <!-- 预检查:只有当存在重复行时才执行后续操作 -->
    <preConditions onFail="MARK_RAN">
        <sqlCheck expectedResult="0">
            SELECT COUNT(*) FROM (
                SELECT target_column FROM foo GROUP BY target_column HAVING COUNT(*) > 1
            ) AS duplicate_rows;
        </sqlCheck>
    </preConditions>

    <!-- 删除重复行:保留每个重复组中ID最大的那条记录(可根据需求调整) -->
    <sql>
        DELETE FROM foo
        WHERE id NOT IN (
            SELECT MAX(id)
            FROM foo
            GROUP BY target_column
            HAVING COUNT(*) > 1
        ) AND target_column IN (
            SELECT target_column
            FROM foo
            GROUP BY target_column
            HAVING COUNT(*) > 1
        );
    </sql>

    <!-- 添加唯一约束 -->
    <addUniqueConstraint
        tableName="foo"
        columnNames="target_column"
        constraintName="uc_foo_target_column"/>
</changeSet>

关键细节说明

  • 重复行清理逻辑:上面的SQL会针对target_column分组,找出重复的记录,只保留每组中id最大的那条(如果你的表没有id列,可以换成其他唯一标识,比如created_at最早/最晚的记录,调整MAX(id)为对应的字段即可)。
  • 预检查的作用:添加<preConditions>可以避免在没有重复行时执行删除操作,让changeset更安全,不会做无用功。
  • 多列唯一约束:如果你的唯一约束是由多个列组成的,只需要把GROUP BY和columnNames里的字段换成对应的多列即可,比如GROUP BY col1, col2和columnNames="col1, col2"。

注意事项

  1. 执行前一定要备份数据,生产环境操作数据容不得半点马虎!
  2. 确保这个新的changeset在插入重复数据的旧changeset之后执行,Liquibase会按changeset的id顺序执行,所以id要比旧的大。
  3. 如果你的数据库是MySQL,注意在子查询中使用表别名避免报错;如果是其他数据库,可能需要微调SQL语法,但核心逻辑是一致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:00:05