ruby-on-rails - Postgres : Default for column (string) cannot be cast automatically to type enum

标签 ruby-on-rails postgresql enums

我在表中有一个 status 列,我想将其作为枚举。最初我将该字段创建为整数,认为我会使用内置的 Rails 枚举功能。结果证明至少需要 Rails 4.1,但我使用的是 4.0,升级过程需要一些时间。

但考虑到这一切是如何工作的,我意识到我可以一个 ActiveRecord 枚举一个 postgres 枚举,但不能同时拥有。我认为从长远来看,最好有一个更明确的 postgres 枚举。因此,我编写了一个迁移程序,将 status 列从整数转换为枚举。

execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
change_column :site_applications, :status, "status_options USING status::status_options"

但是,我得到这个错误:

PG::CannotCoerce: ERROR:  cannot cast type integer to status_options
ALTER TABLE "site_applications" ALTER COLUMN "status" TYPE status_options USING status::status_options

到目前为止,我在搜索中看到的一切都告诉我应该有效,但事实并非如此。我想也许问题是我不能从整数到枚举。就这样吧。我的解决方案是先将列转换为字符串,然后尝试将其转换为枚举。

change_column :site_applications, :status, :string
execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
change_column :site_applications, :status, "status_options USING status::status_options"

这给了我以下错误:

PG::DatatypeMismatch: ERROR:  default for column "status" cannot be cast automatically to type status_options
ALTER TABLE "site_applications" ALTER COLUMN "status" TYPE status_options USING status::status_options

这让我相信这与默认值有关,所以我尝试在 change_column 声明中指定默认值:

change_column :site_applications, :status, :string, default: "pending"

这成功地将列更改为默认值为“pending”的字符串,但是 change_column 失败并出现相同的“default for column”错误。

我意识到我可以简单地将所有列放在一起,然后按照我想要的方式重新创建它,但在这一点上这是后代的问题。为什么我不能将列从整数或字符串转换为枚举?有人吗?

更新接受的答案

根据下面 Gary 的回答,这是有效的迁移。

def up
  execute "ALTER TABLE site_applications ALTER status DROP DEFAULT;"
  execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
  change_column :site_applications, :status, "status_options USING status::status_options", default: "pending"
end

def down
  change_column :site_applications, :status, :string, default: "pending"
  execute "DROP TYPE status_options;"
end

最佳答案

您需要在更改之前从列中删除默认值,因为默认值设置为对旧列类型有效但与新类型不兼容的值。

alter table schema.site_applications alter status drop default

然后您可以更改列类型。最后,一旦应用了新的列类型,您就可以为表添加一个新的默认值。

alter table schema.site_applications alter status set default 'pending'::status_options

关于ruby-on-rails - Postgres : Default for column (string) cannot be cast automatically to type enum,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31567599/

相关文章:

c++ - 如何在 C++ 代码中使用 "c-style flags enum"?

mysql - 'where clause' Rails 4 中的未知列

ruby-on-rails - rails 4 : Creating point rules using merit gem

sql - 如何在一列中制作一个 id 数组是 Postgresql 数据库?

mysql - UPDATE 查询中列的表名前缀

node.js - 如何从 AWS RDS 连接到没有 "database"名称的 PostgreSQL 数据库

c++ - 将一个枚举映射到另一个枚举

java - 关于枚举的问题

ruby-on-rails - rails 4 : Does Devise address session fixation by resetting session after login?

ruby-on-rails - 在后台作业后触发页面的重新加载