Как добавить столбец в SQL

Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.

Базовый синтаксис

ALTER TABLE users ADD COLUMN phone VARCHAR(20);

1. Несколько колонок сразу

Postgres / SQL Server

ALTER TABLE users
ADD COLUMN phone VARCHAR(20),
ADD COLUMN address TEXT,
ADD COLUMN created_at TIMESTAMP DEFAULT NOW();

MySQL

ALTER TABLE users
ADD COLUMN phone VARCHAR(20),
ADD COLUMN address TEXT;

2. С default значением

ALTER TABLE users
ADD COLUMN status VARCHAR(20) DEFAULT 'active';

Для существующих строк проставится 'active'.

3. NOT NULL + default

ALTER TABLE users
ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT NOW();

Важно: NOT NULL без DEFAULT на заполненную таблицу падает (куда deвать старые строки?). DEFAULT обязателен.

4. NOT NULL без default (двухшаговый процесс)

-- шаг 1: добавить nullable
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

-- шаг 2: заполнить
UPDATE users SET phone = 'N/A' WHERE phone IS NULL;

-- шаг 3: сделать NOT NULL
ALTER TABLE users ALTER COLUMN phone SET NOT NULL;

5. Колонка по формуле (computed / generated)

Postgres 12+

ALTER TABLE users
ADD COLUMN full_name VARCHAR(200)
GENERATED ALWAYS AS (first_name || ' ' || last_name) STORED;

MySQL

ALTER TABLE users
ADD COLUMN full_name VARCHAR(200)
AS (CONCAT(first_name, ' ', last_name)) STORED;

Virtual vs stored:

  • VIRTUAL — вычисляется при чтении
  • STORED — сохраняется физически

6. Колонка с FK

ALTER TABLE orders
ADD COLUMN manager_id INT REFERENCES managers(id);

Или отдельно:

ALTER TABLE orders ADD COLUMN manager_id INT;
ALTER TABLE orders
ADD CONSTRAINT fk_orders_manager
FOREIGN KEY (manager_id) REFERENCES managers(id);

7. Колонка в определённом месте (MySQL)

MySQL позволяет управлять порядком:

-- в конец (default)
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

-- первой
ALTER TABLE users ADD COLUMN id INT FIRST;

-- после конкретной колонки
ALTER TABLE users ADD COLUMN phone VARCHAR(20) AFTER email;

Postgres не поддерживает управление порядком — только в конец.

8. Большие таблицы (миллионы строк)

-- на миллиардах строк — ALTER TABLE блокирует таблицу
ALTER TABLE big_table ADD COLUMN new_col INT NOT NULL DEFAULT 0;

В Postgres 11+ добавление колонки с DEFAULT — fast (без переписывания).

Для старых версий или MySQL — можно сделать shadow-таблицу и переименовать.

9. Добавить индекс на новую колонку

ALTER TABLE users ADD COLUMN country_code VARCHAR(2);

-- обновить значения
UPDATE users SET country_code = ...;

-- создать индекс
CREATE INDEX idx_users_country ON users(country_code);

10. UNIQUE constraint при добавлении

ALTER TABLE users
ADD COLUMN employee_code VARCHAR(20) UNIQUE;

Или отдельно:

ALTER TABLE users ADD COLUMN employee_code VARCHAR(20);
ALTER TABLE users ADD CONSTRAINT uq_emp_code UNIQUE (employee_code);

Типичные типы данных

Данные Postgres MySQL
Строка (короткая) VARCHAR(n) VARCHAR(n)
Строка (длинная) TEXT TEXT
Целое INT, BIGINT INT, BIGINT
Decimal NUMERIC(p,s) DECIMAL(p,s)
Float REAL, DOUBLE PRECISION FLOAT, DOUBLE
Boolean BOOLEAN TINYINT(1)
Date DATE DATE
Timestamp TIMESTAMP, TIMESTAMPTZ DATETIME, TIMESTAMP
JSON JSONB JSON
UUID UUID CHAR(36) или BINARY(16)

Откатить (удалить колонку)

ALTER TABLE users DROP COLUMN phone;

Осторожно: данные удалятся без возможности восстановления.

Частые ошибки

NOT NULL без DEFAULT на непустой таблице

-- ошибка
ALTER TABLE users ADD COLUMN required VARCHAR(10) NOT NULL;

-- правильно
ALTER TABLE users ADD COLUMN required VARCHAR(10) NOT NULL DEFAULT 'x';

Забыть про миграции

В production изменения схемы делают через миграции (Alembic, Flyway, Liquibase), а не вручную.

Длинная ALTER TABLE на prod

Блокирует таблицу. Делайте в техническое окно или через NO REWRITE (Postgres 11+).

Не обновить запросы

После добавления колонки старые SELECT * могут получать неожиданные данные.

Связанные темы

FAQ

ALTER TABLE блокирует таблицу?

Зависит от СУБД и операции. Postgres 11+ с DEFAULT — нет. Старые версии — да.

Можно ли добавить колонку с NULL и сделать NOT NULL потом?

Да. Добавить → заполнить → ALTER COLUMN SET NOT NULL.

Где должна быть колонка — в конце или где-то?

В Postgres — только в конце. В MySQL — где угодно (FIRST, AFTER).

Удаление колонки мгновенное?

В Postgres — почти да (помечает invisible). В MySQL — может перестраивать таблицу (долго).


Тренируйте SQL — откройте тренажёр с 1500+ вопросами для собесов.