使用 PostgreSQL 更新 Laravel 迁移中的枚举列

Posted

技术标签:

【中文标题】使用 PostgreSQL 更新 Laravel 迁移中的枚举列【英文标题】:Update enum column in Laravel migration using PostgreSQL 【发布时间】:2015-09-01 15:30:41 【问题描述】:

根据this answer,如果我想在mysql 中更新enum,我必须运行原始查询。但是对于 PostgreSQL,我不能使用这个查询,并且 Laravel 中 PostgreSQL 的枚举类型似乎很奇怪。

有没有办法在 postgreSQL 的迁移中更新枚举?

【问题讨论】:

【参考方案1】:

Laravel 对 character varying 使用约束以用于 enum

假设有一个表mytable 有一个枚举列status,我们必须删除约束(命名为tablename_columnname_check) 然后将其添加到这样的迁移中:

DB::transaction(function () 
    DB::statement('ALTER TABLE mytable DROP CONSTRAINT mytable_status_check;');
    DB::statement('ALTER TABLE mytable ADD CONSTRAINT mytable_status_check CHECK (status::TEXT = ANY (ARRAY[\'pending\'::CHARACTER VARYING, \'accepted\'::CHARACTER VARYING, \'canceled\'::CHARACTER VARYING]::TEXT[]))');
);

解决了问题,希望对你有帮助!

【讨论】:

正是我想要的。只是为了删除约束并使其成为 VARCHAR。枚举不好玩。只需使用 VARCHAR 并让您的代码进行验证。【参考方案2】:

要扩展 @rap-2-h 的答案 - 这是您可以使用的通用方法:

/**
 * Alter an enum field constraints
 * @param $table
 * @param $field
 * @param array $options
 */
protected function alterEnum($table, $field, array $options) 

    $check = "$table_$field_check";

    $enumList = [];

    foreach($options as $option) 
        $enumList[] = sprintf("'%s'::CHARACTER VARYING", $option);
    

    $enumString = implode(", ", $enumList);

    DB::transaction(function () use ($table, $field, $check, $options, $enumString) 
        DB::statement(sprintf('ALTER TABLE %s DROP CONSTRAINT %s;', $table, $check));
        DB::statement(sprintf('ALTER TABLE %s ADD CONSTRAINT %s CHECK (%s::TEXT = ANY (ARRAY[%s]::TEXT[]))', $table, $check, $field, $enumString));
    );


示例用法:

$this->alterEnum('mytable', 'status', ['pending', 'accepted', 'canceled']);

请注意,如果您要删除表中使用的约束,则需要将所有实例重命名为列表中的某个名称,或者在运行此函数之前删除所有实例

【讨论】:

以上是关于使用 PostgreSQL 更新 Laravel 迁移中的枚举列的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Laravel Eloquent 更新 PostgresQL 中 jsonb 列的多个“键”

在 laravel 中使用多对多关系同步:PostgreSQL 数据透视表不更新

Laravel 5 + PostgreSQL:“未配置数据库 [postgres]。”错误

Laravel (Eloquent) 不更新数据库

在 MAMP 中使用 Laravel 设置 PostgreSQL

为啥 distinct 不能与 Laravel + Postgresql 一起使用?