New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Добавление новой колонки NOT NULL #12

Closed
sgrinko opened this Issue Mar 19, 2018 · 10 comments

Comments

Projects
None yet
3 participants
@sgrinko

sgrinko commented Mar 19, 2018

добавил в таблицу новую колонку:
job_number smallint DEFAULT 0 NOT NULL
сгенерировался код:
ALTER TABLE checksync_tables
ADD COLUMN job_number smallint;

ALTER TABLE ONLY checksync_tables
ALTER COLUMN job_number SET DEFAULT 0;

ALTER TABLE ONLY checksync_tables
ALTER COLUMN job_number SET NOT NULL;

к сожалению этот код просто так выполнить невозможно.
1-я строка добавит NULL поле
2-я строка объявит что для insert/update надо заполнить поле значением null
3-я строка попытается сделать поле NOT NULL но конечно у неё это не получится, так как в таблице все строки на данный момент есть NULL

для данной операции ожидалась команда
ALTER TABLE checksync_tables
ADD COLUMN job_number smallint NOT NULL DEFAULT 0;

ваш вариант генерации кода я использую в своих PRE скриптах, когда нужно в цикле мелкими пакетами обработать большую таблицу. Но это ручная работа и такой скрипт пишется специально и вручную. В этом случаем между 2-й и 3-й строкой стоит код замены всех строк с NULL на DEFAULT значение.

@asaushkin

This comment has been minimized.

Show comment
Hide comment
@asaushkin

asaushkin Mar 19, 2018

Contributor

Скрипт для воспроизведения:

create table checksync_tables as
	select generate_series(1, 5) as id;

ALTER TABLE checksync_tables
  ADD COLUMN job_number smallint;

ALTER TABLE ONLY checksync_tables
  ALTER COLUMN job_number SET DEFAULT 0;

ALTER TABLE ONLY checksync_tables
  ALTER COLUMN job_number SET NOT NULL;
Contributor

asaushkin commented Mar 19, 2018

Скрипт для воспроизведения:

create table checksync_tables as
	select generate_series(1, 5) as id;

ALTER TABLE checksync_tables
  ADD COLUMN job_number smallint;

ALTER TABLE ONLY checksync_tables
  ALTER COLUMN job_number SET DEFAULT 0;

ALTER TABLE ONLY checksync_tables
  ALTER COLUMN job_number SET NOT NULL;

@asaushkin asaushkin added the bug label Mar 19, 2018

@asaushkin

This comment has been minimized.

Show comment
Hide comment
@asaushkin

asaushkin Mar 19, 2018

Contributor

Я помню, мы этот кейс обсуждали в своё время и пришли к выводу, что текущее поведение (т.е. когда дефолтные значения выставляются только для новых записей) наиболее приемлемо для существующих данных.

Нужно подумать об опции для изменения поведения.

Contributor

asaushkin commented Mar 19, 2018

Я помню, мы этот кейс обсуждали в своё время и пришли к выводу, что текущее поведение (т.е. когда дефолтные значения выставляются только для новых записей) наиболее приемлемо для существующих данных.

Нужно подумать об опции для изменения поведения.

@sgrinko

This comment has been minimized.

Show comment
Hide comment
@sgrinko

sgrinko Mar 19, 2018

Разъединение такой команды на части хорошо в случае когда мы хотим добавить поле с DEFAULT значением но не NOT NULL.
То есть у нас есть большая таблица и мы добавляем поле
job_number smallint DEFAULT 0 NULL
то, если сделать 1 командой
ALTER TABLE checksync_tables ADD COLUMN job_number smallint NULL DEFAULT 0;
то ВСЕ строки заполнятся значением 0, что не желательно скорее всего (в этой точке как минимум будем долго ждать выполнения команды).
таким образом разъединив это на 2 команды мы получим:
ALTER TABLE checksync_tables
ADD COLUMN job_number smallint;

ALTER TABLE ONLY checksync_tables
ALTER COLUMN job_number SET DEFAULT 0;
быстрое выполнение, а уже потом сможем сами запустить свой POST скрипт заполнения DEFAULT значения пакетами.
Итог:
NULL поле - 2 команды + возможно POST скрипт
NOT NULL - нужно генерить 1 команду и скорее всего потребуется PRE скрипт.
такие скрипты конечно будет писать DBA вручную, хотя конечно шаблончик в папку миграции можно и положить :)

sgrinko commented Mar 19, 2018

Разъединение такой команды на части хорошо в случае когда мы хотим добавить поле с DEFAULT значением но не NOT NULL.
То есть у нас есть большая таблица и мы добавляем поле
job_number smallint DEFAULT 0 NULL
то, если сделать 1 командой
ALTER TABLE checksync_tables ADD COLUMN job_number smallint NULL DEFAULT 0;
то ВСЕ строки заполнятся значением 0, что не желательно скорее всего (в этой точке как минимум будем долго ждать выполнения команды).
таким образом разъединив это на 2 команды мы получим:
ALTER TABLE checksync_tables
ADD COLUMN job_number smallint;

ALTER TABLE ONLY checksync_tables
ALTER COLUMN job_number SET DEFAULT 0;
быстрое выполнение, а уже потом сможем сами запустить свой POST скрипт заполнения DEFAULT значения пакетами.
Итог:
NULL поле - 2 команды + возможно POST скрипт
NOT NULL - нужно генерить 1 команду и скорее всего потребуется PRE скрипт.
такие скрипты конечно будет писать DBA вручную, хотя конечно шаблончик в папку миграции можно и положить :)

@Endeavourl

This comment has been minimized.

Show comment
Hide comment
@Endeavourl

Endeavourl Mar 19, 2018

Contributor

Да, именно кейс без NOT NULL рассматривался, когда мы меняли это поведение (задача 3755 во внутреннем трекере).

Для NOT NULL видится опциональное добавление команды наподобие:

UPDATE t_table SET c_column = DEFAULT WHERE c_column IS NULL;

перед выставлением NOT NULL.

Contributor

Endeavourl commented Mar 19, 2018

Да, именно кейс без NOT NULL рассматривался, когда мы меняли это поведение (задача 3755 во внутреннем трекере).

Для NOT NULL видится опциональное добавление команды наподобие:

UPDATE t_table SET c_column = DEFAULT WHERE c_column IS NULL;

перед выставлением NOT NULL.

@asaushkin

This comment has been minimized.

Show comment
Hide comment
@asaushkin

asaushkin Mar 19, 2018

Contributor

@Endeavourl А почему определение дефолта не перенести в стейтмент создания колонки?

Contributor

asaushkin commented Mar 19, 2018

@Endeavourl А почему определение дефолта не перенести в стейтмент создания колонки?

@sgrinko

This comment has been minimized.

Show comment
Hide comment
@sgrinko

sgrinko Mar 19, 2018

Согласен с @Endeavourl
а DBA уже заменит эту строку на свой цикл при необходимости.
@asaushkin, DEFAULT в стейтмент создания колонки сразу заполнит её, а это долго и такой код нужно как-то выискивать и заменять

sgrinko commented Mar 19, 2018

Согласен с @Endeavourl
а DBA уже заменит эту строку на свой цикл при необходимости.
@asaushkin, DEFAULT в стейтмент создания колонки сразу заполнит её, а это долго и такой код нужно как-то выискивать и заменять

@asaushkin

This comment has been minimized.

Show comment
Hide comment
@asaushkin

asaushkin Mar 19, 2018

Contributor

Ок, можно и так.

Contributor

asaushkin commented Mar 19, 2018

Ок, можно и так.

@Endeavourl

This comment has been minimized.

Show comment
Hide comment
@Endeavourl

Endeavourl Mar 19, 2018

Contributor

@asaushkin
Апдейтом покроется выставление NOT NULL как при создании, так и при изменении колонки, и вообще так проще.
Единственно, апдейты надо будет добавить в опасные выражения.

Contributor

Endeavourl commented Mar 19, 2018

@asaushkin
Апдейтом покроется выставление NOT NULL как при создании, так и при изменении колонки, и вообще так проще.
Единственно, апдейты надо будет добавить в опасные выражения.

@asaushkin asaushkin added enhancement and removed bug labels Mar 28, 2018

@Endeavourl

This comment has been minimized.

Show comment
Hide comment
@Endeavourl

Endeavourl Oct 8, 2018

Contributor

исправлено в a4675b3

Contributor

Endeavourl commented Oct 8, 2018

исправлено в a4675b3

@Endeavourl Endeavourl closed this Oct 8, 2018

@sgrinko

This comment has been minimized.

Show comment
Hide comment
@sgrinko

sgrinko Oct 9, 2018

Спасибо!
В 11 версии появилась поддержка быстрого добавления DEFAULT значений...
По возможности учтите эту возможность если идет построение скрипта для 11-й и выше версии.

sgrinko commented Oct 9, 2018

Спасибо!
В 11 версии появилась поддержка быстрого добавления DEFAULT значений...
По возможности учтите эту возможность если идет построение скрипта для 11-й и выше версии.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment