Обновите столбец перечисления в миграции Laravel с помощью PostgreSQL

Согласно этому ответу, мне нужно выполнить необработанный запрос, если я хочу обновить enum в MySQL. Но с PostgreSQL я не могу использовать этот запрос, а тип enum для PostgreSQL в Laravel кажется странным.

Есть ли способ обновить перечисление при миграции для postgreSQL?


person rap-2-h    schedule 16.06.2015    source источник


Ответы (2)


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[]))');
});

Это решает проблему, надеюсь, что это может помочь!

person rap-2-h    schedule 17.06.2015
comment
Именно то, что я искал. Просто чтобы удалить ограничение и сделать его VARCHAR. перечисления не весело работать. Просто используйте VARCHAR и позвольте вашему коду выполнить проверку. - person ultrasamad; 06.09.2020

Чтобы расширить ответ @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']);

Обратите внимание: если вы удаляете ограничение, которое используется в таблице, вам нужно будет либо переименовать все экземпляры во что-то, что будет в списке, либо удалить все экземпляры перед запуском этой функции.

person Zak Henry    schedule 24.03.2016