将布尔列类型更改为int

时间:2016-03-31 20:25:10

标签: ruby-on-rails ruby postgresql ruby-on-rails-4 rails-migrations

我的Postgres DB表中有一个列是布尔类型。我想将它更改为整数,因为我需要的不仅仅是该列中的true / false。

我还想将所有真值更改为1,将假值更改为2.

这是否可以在Rails中轻松完成?我试图通过迁移文件和迁移我的数据库来做到这一点。

2 个答案:

答案 0 :(得分:13)

是的,您可以通过一次迁移进行此更改。唯一棘手的部分是需要告诉数据库如何将布尔值转换为整数。

执行此操作的方法是使用ALTER TABLE中的USING子句提供映射。原始SQL版本如下所示:

alter table models
alter column c type integer
using case when c then 1 else 2 end

因此转化为迁移:

def change
  change_column :models, :c, :integer, :using => 'case when c then 1 else 2 end'
end

布尔列只能包含TRUEFALSE,因此简单CASE就足够了。如果你允许NULL并希望保留它们,那么:

:using => 'case when c is null then null when c then 1 else 2 end'

应该这样做。

当然,您必须更新所有代码才能正确使用这些新整数。

答案 1 :(得分:2)

您真的需要为此修改数据库吗?一种可能的解决方案是创建一个包装器方法来为您处理这个问题。假设您有一个名为mycol的布尔列,那么您可以编写一个透明地处理此逻辑而不修改底层数据库的包装器方法。

在您的ActiveRecord模型中

def mycol
  read_attribute(:boolcol) ? 1 : 2
end

def mycol=(value)
  write_attribute(:mycol, value == 1)
end

因此,例如,运行u.mycol = 1 && u.save会将false写入数据库,而u.reload.mycol将返回1.

但是,如果真的需要进行迁移,那么创建一个新的整数列来取代原始的布尔列。不要删除或修改现有列,因为要确保您不会破坏或破坏数据。

创建新列后,创建一个rake任务来迭代所有现有记录(使用find_each方法进行迭代)并根据原始布尔值设置新列的整数值柱。一旦您验证了数据的完整性,您就可以删除原始布尔列并将其替换为新创建的列。

相关问题