I need to change the column type of all primary keys in all tables to the UUID format.
How do I migrate without triggering the foreign key checks?
I have tried the following 2 things below, but both still trigger the error:
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 version: 7.0.4.3
MariaDB version: 11.1.2
You have woefully underestimated how much of a ordeal changing the primary key type is. If you want to change the primary key type beyond just changing numerical types you have to actually update all the related tables first to avoid orphaning the records in thoses tables.
The outline of the process is:
cities.uiidUUID type column. Don't touch theidcolumn for now.other_table.city_uuidcolumn. It should be nullable and you can skip the foreign key constraint for now.other_table.city_uuidwith thecities.uiid. This can either be done withOtherModel.include(:city).find_each { |om| om.update(city_uuid: om.city.uiid) }or by usingUPDATE ALLwith a subquery or lateral join. The former is sufficient for small data sets and the later will be faster by an order of magintidue as it doesn't result in N+1 write queries.other_table.city_idcolumn. This will take care of the foreign key restraint problem.cities.id. This may require you to remove the index first.cities.uuidtocities.id.other_table.city_uuidtoother_table.city_id, add a foreign key constraint and make it non-nullable (if that's applicable).The steps 3-5 must be repeated for every foreign key column in your schema.