Rails:如何在不触发外键检查(引用完整性检查)的情况下进行迁移?

问题描述 投票:0回答:1

我需要将所有表中所有主键的列类型更改为

UUID
格式。

如何在不触发外键检查的情况下进行迁移?

我尝试了以下两件事,但仍然触发错误:

Mysql2::Error: Cannot change column 'id': used in a foreign key constraint 'fk_rails_6010a70481' of table 'project_development.some_other_table'

.

class JustAnotherMigration < ActiveRecord::Migration[7.0]

  def change
    ActiveRecord::Base.connection.disable_referential_integrity do
      change_column :cities, :id, :uuid
    end
  end

end

.

class JustAnotherMigration < ActiveRecord::Migration[7.0]

  def change
    ActiveRecord::Base.connection.execute "SET FOREIGN_KEY_CHECKS=0;"
    change_column :cities, :id, :uuid
    ActiveRecord::Base.connection.execute "SET FOREIGN_KEY_CHECKS=1;"
  end

end

Rails 版本:

7.0.4.3

MariaDB 版本:

11.1.2

ruby-on-rails migration referential-integrity
1个回答
0
投票

您严重低估了更改主键类型的痛苦程度。如果您想要更改主键类型而不仅仅是更改数字类型,则必须首先实际更新所有相关表,以避免孤立这些表中的记录。

所以这里的流程基本上应该是:

  1. 备份您的数据库。
  2. 创建一个
    cities.uiid
    UUID 类型列。暂时不要触碰
    id
    栏。
  3. 创建一个
    other_table.city_uuid
    列。它应该可以为空,您现在可以跳过外键约束。
  4. other_table.city_uuid
    填充
    cities.uiid
    。这可以通过
    OtherModel.include(:city).find_each { |om| om.update(city_uuid: om.city.uiid) }
    或通过使用
    UPDATE ALL
    和子查询来完成。
  5. 现在您已完成重新创建表之间的关系,删除
    other_table.city_id
    列。这将解决外键约束问题。
  6. 删除
    cities.id
    。这可能需要您先删除索引。
  7. cities.uuid
    重命名为
    cities.id
  8. other_table.city_uuid
    重命名为
    other_table.city_id
    ,添加外键约束并将表更改为不可空(如果适用)。
© www.soinside.com 2019 - 2024. All rights reserved.