我需要将所有表中所有主键的列类型更改为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
1条答案
按热度按时间hpxqektj1#
不幸的是,你低估了改变主键类型的痛苦程度。如果你想改变主键类型,而不仅仅是改变数值类型,你必须首先更新所有相关的表,以避免这些表中的记录孤立。
该过程的概要是:
1.备份您的数据库。
1.创建一个
cities.uiid
UUID类型列。暂时不要触摸id
列。1.创建一个
other_table.city_uuid
列。它应该是可空的,现在可以跳过外键约束。1.用
cities.uiid
填充other_table.city_uuid
。这可以用OtherModel.include(:city).find_each { |om| om.update(city_uuid: om.city.uiid) }
完成,也可以用UPDATE ALL
和子查询或横向连接完成。前者对于小数据集足够了,后者会更快,因为它不会导致N+1个写查询。1.现在,您已经完成了重新创建表之间的关系,删除
other_table.city_id
列。这将解决外键约束问题。1.删除
cities.id
。这可能需要您首先删除索引。1.从
cities.uuid
到cities.id
。1.将
other_table.city_uuid
转换为other_table.city_id
,添加一个外键约束并使其不可空(如果适用)。必须对模式中的每个外键列重复步骤3-5。