我在表格中有一个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
失败并显示相同的“默认列”错误。
我意识到我可以简单地将列放在一起,然后按照我想要的方式重新创建它,但此时这是后代的问题。为什么我不能将列从整数或字符串转换为枚举?任何人吗?
接受回复更新
根据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
答案 0 :(得分:14)
您需要从更改前的列中删除默认值,因为默认值设置为对旧列类型有效但与新类型不兼容的值。
alter table schema.site_applications alter status drop default
然后您可以更改列类型。最后,一旦应用了新的列类型,您就可以为表添加新的默认值。
alter table schema.site_applications alter status set default 'pending'::status_options