我的Postgres DB表中有一个列是布尔类型。我想将它更改为整数,因为我需要的不仅仅是该列中的true / false。
我还想将所有真值更改为1,将假值更改为2.
这是否可以在Rails中轻松完成?我试图通过迁移文件和迁移我的数据库来做到这一点。
答案 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
布尔列只能包含TRUE
或FALSE
,因此简单CASE
就足够了。如果你允许NULL
并希望保留它们,那么:
:using => 'case when c is null then null when c then 1 else 2 end'
应该这样做。
当然,您必须更新所有代码才能正确使用这些新整数。
答案 1 :(得分:2)
您真的需要为此修改数据库吗?一种可能的解决方案是创建一个包装器方法来为您处理这个问题。假设您有一个名为mycol
的布尔列,那么您可以编写一个透明地处理此逻辑而不修改底层数据库的包装器方法。
:
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
方法进行迭代)并根据原始布尔值设置新列的整数值柱。一旦您验证了数据的完整性,您就可以删除原始布尔列并将其替换为新创建的列。