如何更改 Heroku 中的列类型?

Posted

技术标签:

【中文标题】如何更改 Heroku 中的列类型?【英文标题】:How do I change column type in Heroku? 【发布时间】:2011-03-05 19:00:00 【问题描述】:

我正在尝试将 db:migrations 耙入我的 heorku 实例中,但出现错误。常见问题解答将我的错误描述如下:

无法更改列类型

示例:PGError: ERROR: column “verified_at”不能转换为类型 “日期”

原因:PostgreSQL 不知道怎么做 将该表中的所有行转换为 指定类型。很可能意味着 你有一个整数或字符串 那个专栏。

解决方案:检查您的记录并 确保它们可以转换为 新型。有时更容易 只是避免使用change_column, 重命名/创建新列 而是。

我现在如何更改此迁移。这是我遇到的问题。对于我的联系人表,我创建了以下内容:

  t.string :date_entered

在以后的迁移中,我执行以下操作:

 change_column :contacts, :date_entered, :date

这个 change_column 似乎是问题所在。

我应该...手动更改迁移吗?有没有办法可以清理表中的数据(我不知道 Heroku 会识别表中的数据,因为我正在做 rake)。

我显然需要更改这个值,它在我的整个应用程序中都会用到。谢谢。

这就是我正在尝试的……想法?

def self.up
  #change_column :contacts, :date_entered, :date
  #this fails in postgres, so trying the same outcome 

  rename_column :contacts, :date_entered, :date_entered_old
  add_column :contacts, :date_entered, :date
  remove_column :contacts, :date_entered_old
end

def self.down
  add_column :contacts, :date_entered_old
  remove_column :contacts, :date_entered
  rename_column :contacts, :date_entered_old, :date_entered
end

【问题讨论】:

【参考方案1】:

执行以下操作:

    重命名A列 将新列 B 创建为日期 将数据从 A 移动到 B 删除 A

换句话说

def self.up
  rename_column :contacts, :date_entered, :date_entered_string
  add_column :contacts, :date_entered, :date

  Contact.reset_column_information
  Contact.find_each  |c| c.update_attribute(:date_entered, c.date_entered_string)  
  remove_column :contacts, :date_entered_string
end

【讨论】:

+1 表示#reset_column_information,这是我以前从未见过的。这看起来在非常罕见的时候会派上用场。 如果您有大量数据,update_attribute 循环可能需要很长时间。运行这个一次性完成的原始 sql 语句要快得多。 ActiveRecord::Base.connection.execute("update table set new_column =old_column"); 如果旧值需要强制转换也没问题,请在更新调用中使用 postgres 强制转换。【参考方案2】:

这是 Simone Carletti 解决方案的修改和测试版本

class ModifyContacts < ActiveRecord::Migration
  def self.up
    rename_column :contacts, :date_entered, :date_entered_string
    add_column :contacts, :date_entered, :date

    Contact.reset_column_information
    Contact.find(:all).each  |contact| contact.update_attribute(:date_entered, contact.date_entered_string) 
    remove_column :contacts, :date_entered_string
  end
end

【讨论】:

你确实想要那个find_each。您的版本会将整个表读入内存,而 find_each 会同时获取一些行数。

以上是关于如何更改 Heroku 中的列类型?的主要内容,如果未能解决你的问题,请参考以下文章

你如何更改rails中的列数据类型?

如何更改 firebird3 中的列类型

如何在不包含新列名和类型的情况下更改现有 Hive 表中的列注释?

更改 DataFrame 中的列数据类型并将其传递到 UDF - PySpark

更改熊猫中的列类型

更改熊猫中的列类型