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

5
根据这个答案,如果我想要更新MySQL中的enum,我必须运行原始查询。但是,在PostgreSQL中,我不能使用此查询,并且Laravel中的PostgreSQL枚举类型似乎很奇怪。 是否有任何方法可以在postgreSQL迁移中更新枚举?
2个回答

11

Laravel在字符变量上使用枚举约束。

假设有一个名为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[]))');
});

它解决了这个问题,希望能有所帮助!


1
正是我要找的。只需删除约束并将其设置为VARCHAR类型。枚举类型很难处理。只需使用VARCHAR类型,让您的代码执行验证即可。 - ultrasamad

4

扩展 @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']);

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接