关于版本:
- rails :5.1.4
- PostgreSQL:9.6.1.0
我有两个具有 ENUM 状态的模型,当我尝试为第二个模型运行迁移时出现此错误:
PG::DuplicateObject: ERROR: type "status" already exists :
CREATE TYPE status AS ENUM ('created', 'published', 'archived'); /Ruby/Projects/Apps/alpsplease/alps_app/db/migrate/20180215204243_add_status_to_experiences.rb:3:in `up'Caused by: ActiveRecord::StatementInvalid: PG::DuplicateObject: ERROR: type "status" already exists : CREATE TYPE status AS ENUM ('created', 'published', 'archived'); /Ruby/Projects/Apps/alpsplease/alps_app/db/migrate/20180215204243_add_status_to_experiences.rb:3:in `up'
Caused by: PG::DuplicateObject: ERROR: type "status" already exists /Ruby/Projects/Apps/alpsplease/alps_app/db/migrate/20180215204243_add_status_to_experiences.rb:3:in `up' Tasks: TOP => db:migrate (See full trace by running task with --trace)
为第二个模型生成相同 ENUM 类型或将现有类型添加到第二个模型的正确方法是什么?因为创建像“status_model”这样的 ENUM 看起来不是理想的解决方案。
迁移代码:
class AddStatusToExperiences < ActiveRecord::Migration[5.1]
def up
execute <<-SQL
CREATE TYPE status AS ENUM ('created', 'published', 'archived');
SQL
add_column :experiences, :status, :status, default: 'created', index: true
end
def down
remove_column :experiences, :status
execute <<-SQL
DROP TYPE status;
SQL
end
end
最佳答案
因为你已经有了一个 status
枚举类型,解决方案非常简单直接:只需将类型指定为 :status
你可以开始了。没有额外的 CREATE TYPE
或 DROP TYPE
在迁移中。
只要知道,如果你修改枚举类型,所有使用它的表当然会在可能的取值范围内受到影响。尽管如此,如果您想在某个时候添加新值,这里有一个提示:您需要为此禁用数据库事务。即
class AddNewStatus < ActiveRecord::Migration[5.0]
disable_ddl_transaction! # enums cannot be altered from within a transaction
def change
execute <<-SQL
ALTER TYPE status ADD VALUE 'foobar';
SQL
end
end
有关共享枚举类型的更多信息,请参阅此帖子: Share enum declaration values between models
如果您不想共享类型(即它们只是偶然具有相同的名称但一组不同的可能值),您可以通过 ALTER TYPE status RENAME TO experience_status
重命名现有类型。并发出另一个 CREATE TYPE
像以前一样使用第二个名称,指的是第二个表的列的新类型。
关于ruby-on-rails - 迁移错误 : ENUM type already exists,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48816339/