58

我已经用谷歌搜索了一下,似乎对我的问题没有满意的答案。

我有一个包含字符串类型列的表。我想运行以下迁移:

class ChangeColumnToBoolean < ActiveRecord::Migration
    def up
        change_column :users, :smoking, :boolean
    end
end

当我运行它时,我收到以下错误

PG::Error: ERROR:  column "smoking" cannot be cast automatically to type boolean
HINT:  Specify a USING expression to perform the conversion.
: ALTER TABLE "users" ALTER COLUMN "smoking" TYPE boolean

我知道我可以使用纯 SQL 执行此迁移,但如果我可以使用 Rails 执行此迁移会更好。我浏览了 Rails 代码,似乎没有这种可能性,但也许有人知道方法?

我不感兴趣: - 纯 SQL - 删除列 - 创建另一列,转换数据,删除原始然后重命名

4

4 回答 4

117

如果列中的字符串smoking已经是有效的布尔值,则以下语句将更改列类型而不会丢失数据:

change_column :users, :smoking, 'boolean USING CAST(smoking AS boolean)'

同样,您可以使用此语句将列转换为整数:

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

我正在使用 Postgres。不确定此解决方案是否适用于其他数据库。

于 2014-01-03T08:35:34.193 回答
34

并非所有数据库都允许更改列类型,通常采用的方法是添加所需类型的新列,带入任何数据,删除旧列并重命名新列。

add_column :users, :smoking_tmp, :boolean

User.reset_column_information # make the new column available to model methods
User.all.each do |user|
  user.smoking_tmp = user.smoking == 1 ? true : false # If smoking was an int, for example
  user.save
end

# OR as an update all call, set a default of false on the new column then update all to true if appropriate.
User.where(:smoking => 1).update_all(:smoking_tmp = true) 

remove_column :users, :smoking
rename_column :users, :smoking_tmp, :smoking
于 2013-06-12T21:20:51.307 回答
8

所以在 postgres 中适合布尔值:

change_column :table_name, :field,'boolean USING (CASE field WHEN \'your any string as true\' THEN \'t\'::boolean ELSE \'f\'::boolean END)'

您可以在表达式中添加更多WHEN-条件THEN

对于其他数据库服务器,表达式将根据您的数据库服务器的语法构造,但原理相同。只有手动转换算法,完全没有 SQL 是不够的。

change_column :table, :field, 'boolean USING CAST(field AS boolean)'仅当字段的内容类似于:true / false / null 时,该语法才适用

于 2015-03-03T14:29:19.413 回答
5

由于我使用的是 Postgres,所以我现在使用 SQL 解决方案。使用的查询:

    execute 'ALTER TABLE "users" ALTER COLUMN "smoking" TYPE boolean USING CASE WHEN "flatshare"=\'true\' THEN \'t\'::boolean ELSE \'f\'::boolean END'

仅当一个字段填充了真/假字符串时才有效(例如,将生成具有强制布尔类型的默认单选按钮集合助手)

于 2013-06-12T21:34:59.527 回答