Ecto迁移修改与回滚问题:如何保留测试数据并更新Schema?
问题解答
一、能否保留测试数据并更新Schema?
可以保留测试数据,但不建议直接修改已执行过的create_products迁移文件——迁移文件设计上应是不可变的,直接修改会导致本地迁移记录与数据库中的版本不一致,后续极易引发数据同步问题。正确操作方式如下:
- 新建一个专门用于添加字段的迁移文件:
mix ecto.gen.migration add_importer_id_to_products -r Mirror.Repo - 在生成的迁移文件中编写添加字段的逻辑:
defmodule Mirror.Repo.Migrations.AddImporterIdToProducts do use Ecto.Migration def change do add :importer_id, :string, table: :products end end - 执行迁移,此操作不会丢失现有测试数据:
mix ecto.migrate -r Mirror.Repo - 同步更新对应的
ProductSchema,添加新字段并修改changeset:defmodule Mirror.Product do use Ecto.Schema import Ecto.Changeset schema "products" do field :importer_id, :string # 新增字段 field :title, :string field :cid, :string field :seller_cids, :string # 其他原有字段 end def changeset(product, attrs) do product |> cast(attrs, [:importer_id, :title, :cid, :seller_cids]) # 原有验证规则 end end
若已修改原迁移文件且未推送到团队仓库/其他环境,也可通过回滚重执行的方式调整,但这会清空products表的测试数据,不推荐:
# 回滚2个版本,会删除products和pictures表 mix ecto.rollback -n 2 -r Mirror.Repo # 重新执行所有迁移 mix ecto.migrate -r Mirror.Repo
二、能否直接修改create_products并回滚create_pictures?
关于回滚create_pictures
可以单独回滚create_pictures迁移,因为它是最后执行的版本,执行命令:
mix ecto.rollback -n 1 -r Mirror.Repo
此操作仅会删除pictures表,不会影响products表的测试数据。
关于修改create_products并回滚
不建议这么做,核心原因:
create_pictures迁移大概率依赖products表(比如外键关联),直接回滚create_products会因表依赖或关联数据存在而失败。- 修改已执行的迁移文件会破坏迁移的可追溯性,导致不同环境的迁移版本不一致,后续维护风险极高。
若确实需要调整products表结构,优先采用新增迁移文件的方式(如第一部分所述),既能保留测试数据,又能保证迁移流程的一致性。
内容的提问来源于stack exchange,提问作者Chen Yu
相关产品推荐
相关产品推荐

