如何解决如何在Rails迁移中将一列包含内容移动到另一个表?
| 我需要将一些列从一个现有表移动到另一表。如何使用Rails迁移进行操作?class AddPropertyToUser < ActiveRecord::Migration
def self.up
add_column :users,:someprop,:string
remove_column :profiles,:someprop
end
def self.down
add_column :profiles,:string
remove_column :users,:someprop
end
end
上面只是创建了新列,但是值保留为空...
我想避免登录数据库以手动更新表。
如果可以通过编程方式移动列值,那么性能特征是什么?它会逐行执行,还是可以批量更新?
解决方法
我最终使用了此迁移(经过测试,它可以正常工作,并且成功回滚):
class AddPropertyToUser < ActiveRecord::Migration
def self.up
add_column :users,:someprop,:string
execute \"UPDATE users u,profiles p SET u.someprop = p.someprop WHERE u.id = p.user_id\"
remove_column :profiles,:someprop
end
def self.down
add_column :profiles,:string
execute \"UPDATE profiles p,users u SET p.someprop = u.someprop WHERE p.user_id = u.id\"
remove_column :users,:someprop
end
end
我喜欢它,因为它避免了在大型数据库上进行逐行更新。
,我将其作为三个迁移或三个部分的迁移来完成。第一部分添加列,第二部分复制数据,第三部分删除列。
听起来中间步骤就是您要问的问题,您可以通过遍历所有用户并设置属性来在ruby中执行此操作,如下所示:
Users.each do |user|
user.someprop = user.profile.some_prop
user.save
end
我不喜欢这种方式,因为它非常慢。我建议像这样执行原始SQL:
execute \"UPDATE users u,profiles p SET u.someprop=p.someprop WHERE u.id=p.user_id\"
这些都假设您的个人资料/用户关联有关,如果我认为有误,则可以调整。
,该语法不适用于Postgres的更高版本。有关Postges 9.4.5的@Eero \'s更新答案,请执行以下操作:
class AddPropertyToUser < ActiveRecord::Migration
def self.up
add_column :users,:string
execute \"UPDATE users u SET someprop = (SELECT p.someprop FROM profiles p WHERE u.id = p.user_id);\"
remove_column :profiles,:string
execute \"UPDATE profiles p SET someprop = (SELECT u.someprop FROM users u WHERE p.user_id = u.id);\"
remove_column :users,:someprop
end
end
,以下UPDATE
语法适用于最新的Postgres版本,并避免了子查询:
class MoveSomePropertyToUser < ActiveRecord::Migration
def self.up
add_column :users,:some_property,:string
execute \"UPDATE users u SET some_property = p.some_property FROM profiles p WHERE u.id = p.user_id;\"
remove_column :profiles,:some_property
end
def self.down
add_column :profiles,:string
execute \"UPDATE profiles p SET some_property = u.some_property FROM users u WHERE p.user_id = u.id;\"
remove_column :users,:some_property
end
end
,您可以使用update_all和/或find_each避免使用硬编码的,特定于数据库的sql语句
,这是我在项目中所做的:
class MoveColumnDataToUsersTable < ActiveRecord::Migration[5.1]
def up
add_column :users,:string
User.find_each do |u|
Profile.create!(user_id: u.id,someprop: someprop)
end
remove_column :profiles,:someprop
end
def down
add_column :profiles,:someprop_data_type
Profile.find_each do |p|
User.find_by(id: p.user_id).update_columns(someprop: p.someprop)
end
Profile.destroy_all
end
end
,对我而言(postgreSQL 9.1)RAW SQL无效。我已经更改了它:
\" UPDATE users u
SET someprop = (SELECT p.someprop
FROM profiles p
WHERE u.id = p.user_id );\"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。