将布尔列类型更改为 int

Changing boolean column type to int

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

我也想把所有的真值改成1,假值改成2。

这在 Rails 中很容易完成吗?我试图通过迁移文件和迁移我的数据库来做到这一点。

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

在您的 ActiveRecord 模型中:

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

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

例如,运行 u.mycol = 1 && u.savefalse 写入数据库,而 u.reload.mycol 将 return 1.

但是,如果确实有必要进行迁移,则创建一个新的整数列来取代原来的布尔列。不要删除或修改现有列,因为要确保您没有损坏或破坏数据。

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

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

这样做的方法是在 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 就足够了。如果您允许 NULLs 并希望保留它们,那么:

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

应该可以解决问题。

当然,您必须更新所有代码才能正确地手动处理这些新整数。