微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在Rails迁移中将一列包含内容移动到另一个表?

如何解决如何在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 举报,一经查实,本站将立刻删除。