好的,那么,当你尝试使用数据类型进行简单的迁移时,它就没什么大不了的了。
但是在某些情况下,当您需要使用正在运行的生产数据库更改主键的类型时。
这个大胆的陈述很重要,因为rails不会为你提供修改id的方法,用“woooah证明它是正确的,它可能会破坏你的数据完整性,所以可怕”。但是,嘿,我需要更改类型并重新填充所有密钥为了这种完整性。
好的,现在你知道了介绍,让我们深入研究一些代码。
以下迁移为您提供了工作数据库,但您也可以删除已迁移的表,因为旧的表变为无用的垃圾。请记住,主题键现在是uuid,我们需要将其设为整数。
class RebuildOrdersIds < ActiveRecord::Migration
def up
remove_column :orders, :id
[:order_transitions, :order_items, :addresses].each do |table|
remove_column table, :order_id
add_column table, :order_id, :integer
end
Order.connection.execute("CREATE SEQUENCE order_index_seq START 100000;")
Order.connection.execute("ALTER TABLE orders ADD COLUMN id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('order_index_seq');")
end
def down
remove_column :orders, :id
Order.connection.execute("DROP SEQUENCE order_index_seq;")
add_column :orders, :id, :uuid, default: 'uuid_generate_v4()'
Order.connection.execute("ALTER TABLE orders ADD CONSTRAINT primakey PRIMARY KEY (id);")
[:order_transitions, :order_items, :addresses].each do |table|
remove_column table, :order_id
add_column table, :order_id, :uuid
end
end
end
如您所见,它会删除旧的PK并创建不同数据类型的新列。
如果您需要保存数据库的完整性,可能需要执行类似的操作。
class RebuildOrdersIds < ActiveRecord::Migration
def up
#creating second temporary column for things. It might as well be new integer column.
[:orders, :order_transitions,
:order_items, :addresses].each do |table|
add_column table, :old_order_id, :uuid
end
#mapping stuff together, setting either new values (start) or copying old ones
mapping = {}
start = 100000
Order.all.each do |o|
mapping[o] = {transitions: o.order_transitions,
items: o.order_items,
address: o.address}
end
mapping.each do |o|
o[0].update_attribute(:old_order_id, o[0].id)
o[1][:transitions].empty? || o[1][:transitions].each do |t|
t.update_attribute(:old_order_id, o[0].id)
end
o[1][:items].empty? || o[1][:items].each do |i|
i.update_attribute(:old_order_id, o[0].id)
end
o[1][:address].nil? || o[1][:address].update_attribute(:old_order_id, o[0].id)
start += 1
end
#remove old columns, add some new
remove_column :orders, :id
[:order_transitions, :order_items, :addresses].each do |table|
remove_column table, :order_id
add_column table, :order_id, :integer
end
#making new column with counter with offset start
Order.connection.execute("CREATE SEQUENCE order_index_seq START #{start};")
Order.connection.execute("ALTER TABLE orders ADD COLUMN id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('order_index_seq');")
end
end
因此,应该有一些代码可以填充“id”值。
麻烦的是,没有任何工作。 #update_attribute都没有 也不是#update_all 也不.id,.save
如何实现所需的结果?