postgresql 我们是否可以更改生产中所有迁移的主键?

zi8p0yeb  于 2022-11-29  发布在  PostgreSQL
关注(0)|答案(1)|浏览(137)

我正在尝试将表主键ID更改为uuid。但问题是数据已经在生产中。有一个选项可以重写整个迁移,但这样我们就丢失了已经拥有的数据。
还有,表之间有太多的关联。那么有没有办法处理这种情况呢?
我们使用Phoenix和长生不老药与postgres为这一点。

3htmauhk

3htmauhk1#

是的。可以通过几个步骤来完成任务,一些步骤对数据库执行原始SQL。

  • migration 1在数据库中创建新列,唯一,非空,类型:uuid(正常迁移)* 并 * 用唯一值填充它(例如,使用ecto UUID生成器)
  • 迁移2使用Ecto.Adapters.SQL.query/4重新分配表中的主键¹
  • 迁移3通过删除外键 * 然后 * 将值从id更新为uuid,* 然后 * 创建指向uuid ²的新外键来更新引用此表的所有其他表

¹大致沿着以下思路(未测试)

defmodule MyRepo.Migrations.ChangeFK do
  def up do
    MyRepo.query("""
    CREATE UNIQUE INDEX CONCURRENTLY foo_pkey_idx ON foo(id);

    ALTER TABLE foos
      DROP CONSTRAINT foo_pkey,
      ADD CONSTRAINT foo_pkey PRIMARY KEY USING INDEX foo_pkey_idx;
    """)
  end

  def down do
    raise "unreversible"
  end
end

²有点像

defmodule MyRepo.Migrations.AlterFK do
  def up do
    MyRepo.query("""
    ALTER TABLE bars DROP CONSTRAINT foo_pkey;

    UPDATE bars SET foo_id = (SELECT uuid FROM foos WHERE id = foo_id);

    ALTER TABLE bars
      ADD CONSTRAINT foo_pkey
      FOREIGN KEY (foo_id)
      REFERENCES foos (uuid);
    """)
  end

  def down do
    raise "unreversible"
  end
end

相关问题