如何将字符串列更改为bigint?

时间:2012-04-30 08:09:48

标签: ruby-on-rails ruby-on-rails-3 postgresql heroku migration

在rails迁移中。如何将字符串类型列更改为bigint?

我有:

t.change :ip_number_from, :integer, :limit => 8

我明白了:

PG::Error: ERROR:  column "ip_number_from" cannot be cast to type bigint

我甚至尝试过两种选择:

change_column :ip_to_countries, :ip_number_from, :integer, :limit => 8
change_column :ip_to_countries, :ip_number_from, :bigint

仍然是同样的错误。

4 个答案:

答案 0 :(得分:13)

Postgres告诉你,该列中存在不知道如何转换的现有数据,因此它需要一个ALTER语句,该列为列提供USING子句以指定如何转换现有值。

不幸的是,您需要删除特定于数据库的代码来完成此操作,或者使用与此处建议的解决方案类似的内容:

http://webjazz.blogspot.co.uk/2010/03/how-to-alter-columns-in-postgresql.html

编辑:以下是您在迁移中直接在SQL中执行此操作的方法:

execute <<-SQL
  ALTER TABLE ip_to_countries
  ALTER COLUMN ip_number_from TYPE bigint USING ip_number_from::bigint
SQL

答案 1 :(得分:3)

你的ip_number_from列是什么?

无论如何,我可能会:

  • 创建一个bigint类型的新列,
  • 通过rails console或rake任务手动将数据从ip_number_from复制到new_column,
  • 删除原始的ip_number_from列
  • 将new_column重命名为ip_number_from

或者你可以像mjtko建议的那样下载到SQL,但我不确定它会更容易。

更新

我抬头看着尤尔的建议。我认为在一次迁移中完成所有这些操作会有点危险,因为您无法真正检查数据的转换/复制是否成功。如果您确实希望在一次迁移中执行此操作,则在您的情况下,它看起来像这样:

def up
  add_column :table, :new_column, :bigint
  Model.reset_column_information
  Model.all.each do |m|
    m.update_attribute :new_column, Model.bigint_from_ip_number_from(m)
  end
  drop_column :table, :ip_number_from
  rename_column :table, :new_column, :ip_number_from
end

您还应该添加相应的向下迁移。

您可以随时将其拆分为多次迁移,并随时查看进度/成功情况。

答案 2 :(得分:0)

我最近读过 - 但不记得在哪里 - 你不能将“字符串”列转换为“int”列,但你可以这样做。从“int”到“string”的转换是不可逆转的迁移操作。

我将在我阅读的文档中搜索并在我找到它时编辑我的帖子。

如果可以的话,最容易做的就是Jure Triglav的建议。 (他在我之前发布了他的答案,但我建议同样的事情;))。

[编辑]我发现我回读的地方:Irreversible Migration tuto

答案 3 :(得分:0)

change_column :table_name, :column_name, 'TYPE bigint USING CAST(column_name AS TYPE bigint)'