Добавление необнуляемого столбца к существующей таблице завершается неудачно. Атрибут "value" игнорируется? - PullRequest
10 голосов
/ 18 января 2012

Справочная информация: у нас есть приложение Grails 1.3.7, и мы используем Liquibase для управления миграциями нашей базы данных.

Я пытаюсь добавить в существующую таблицу новый столбец, который не является пустым.

Моя ревизия выглядит так:

    changeSet(author: "someCoolGuy (generated)", id: "1326842592275-1") {
        addColumn(tableName: "layer") {
            column(name: "abstract_trimmed", type: "VARCHAR(455)", value: "No text") {
                constraints(nullable: "false")
            }
        }
    }

Который должен был вставить значение «Нет текста» в каждую существующую строку и, следовательно, удовлетворять условию «не ноль». Liquibase "Добавить столбец" документы .

Но когда применяются наборы изменений миграции, я получаю следующее исключение:

liquibase.exception.DatabaseException: Error executing SQL ALTER TABLE layer ADD abstract_trimmed VARCHAR(455) NOT NULL: ERROR: column "abstract_trimmed" contains null values

Мне кажется, что он не использует атрибут 'value'.

Если я поменяю свою ревизию на работу, выглядело бы следующим образом, я смогу добиться того же. Но я не хочу (и не должен) делать это.

    changeSet(author: "someCoolGuy (generated)", id: "1326842592275-1") {
        addColumn(tableName: "layer") {
            column(name: "abstract_trimmed", type: "VARCHAR(455)")
        }

        addNotNullConstraint(tableName: "layer", columnName:"abstract_trimmed", defaultNullValue: "No text")
    }

Liquibase действительно игнорирует мой атрибут value, или здесь происходит что-то еще, чего я не вижу?

Я использую Grails 1.3.7, плагин переноса базы данных 1.0, Postgres 9.0

Ответы [ 2 ]

16 голосов
/ 18 января 2012

Краткий ответ

Атрибут «value» не будет работать, если вы добавляете ненулевое ограничение во время создания столбца (это не упоминается в документации ). Сгенерированный SQL не сможет быть выполнен.

Обход

Обходной путь, описанный в этом вопросе, - это путь. Результирующий SQL будет:

  1. Добавить столбец

    ALTER TABLE layer ADD COLUMN abstract_trimmed varchar(455);
    
  2. Установить ненулевое значение для каждой строки

    UPDATE table SET abstract_trimmed = 'No text';
    
  3. Добавить ограничение NOT NULL

    ALTER TABLE layer ALTER COLUMN abstract_trimmed SET NOT NULL;
    

Почему?

Столбец по умолчанию вставляется в столбец только с INSERT. Тег "value" сделает это за вас, но после столбец будет добавлен. Liquibase пытается добавить столбец за один шаг с ограничением NOT NULL:

ALTER TABLE layer ADD abstract_trimmed VARCHAR(455) NOT NULL;

... что невозможно , когда таблица уже содержит строки. Это просто недостаточно умно.

Альтернативное решение

Начиная с PostgreSQL 8.0 (к настоящему времени почти навсегда) альтернативой будет добавление нового столбца с ненулевым DEFAULT предложением:

ALTER TABLE layer ADD COLUMN abstract_trimmed varchar(455) DEFAULT 'No text';

Руководство по ALTER TABLE:

Когда столбец добавляется с ADD COLUMN, все существующие строки в таблице инициализируются значением столбца по умолчанию (NULL, если нет DEFAULT оговорка уточняется).

1 голос
/ 19 декабря 2013

Используйте «defaultValue» вместо «value», чтобы установить значение по умолчанию для нового столбца.

...