7

在 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

4 回答 4

14

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
于 2012-04-30T08:28:41.683 回答
3

您的 ip_number_from 列中有什么?

无论如何,我可能会:

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

或者您可以像 mjtko 建议的那样使用 SQL,但我不确定它是否会更容易。

更新

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

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

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

您始终可以将其拆分为多个迁移,并随时检查进度/成功。

于 2012-04-30T08:30:33.733 回答
0

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

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

如果可以的话,最简单的做法就是 Jure Triglav 的建议。(他在我之前发布了他的答案,但我提出了同样的建议;))。

[编辑] 我找到了我读到的地方:不可逆转的迁移 tuto

于 2012-04-30T08:32:23.707 回答
0

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

于 2021-01-18T05:49:33.193 回答