ALTER TABLE — оператор языка DDL (Data Definition Language, язык определения данных), который изменяет структуру существующей таблицы без удаления хранящихся данных. С его помощью добавляют и убирают столбцы, меняют типы данных, переименовывают поля и управляют ограничениями целостности. Именно это отличает ALTER TABLE от «ядерного» варианта — DROP TABLE с последующим пересозданием: данные остаются на месте, структура меняется «на ходу».
В статье разбираем шесть ключевых операций: ADD COLUMN, DROP COLUMN, MODIFY/ALTER COLUMN, RENAME COLUMN, RENAME TABLE, ADD/DROP CONSTRAINT. Для каждой — рабочий SQL-код с комментариями, объяснение поведения и типичные ошибки. Завершает статью матрица совместимости из 11 операций для MySQL, PostgreSQL, SQL Server, Oracle и SQLite — удобный справочник при переходе между базами данных. Если вам нужен конкретный раздел, используйте заголовки как навигацию.
Учитесь бесплатно за счёт государства
Экономия до 100 000 ₽ на любой программе
ALTER TABLE входит в группу DDL-операторов — наряду с CREATE TABLE, DROP TABLE и TRUNCATE. Принципиальное различие между DDL и DML (Data Manipulation Language, язык манипуляции данными): DML-операторы — INSERT, UPDATE, DELETE — работают со строками внутри таблицы, DDL меняет саму схему: добавляет столбцы, назначает ограничения, переименовывает объекты.
Оператор ALTER TABLE нужен, когда таблица уже содержит данные, но её структура перестала соответствовать задаче. Появилось новое поле, изменился тип данных, требуется ввести ограничение уникальности — пересоздавать таблицу с нуля и заново мигрировать данные дорого и рискованно. ALTER TABLE решает задачу без лишних движений.
Шесть операций, которые разбирает эта статья:
Важный технический момент: в большинстве СУБД ALTER TABLE накладывает блокировку Schema Modification Lock (Sch-M) на всё время операции. Параллельные запросы к таблице ждут завершения. В высоконагруженных системах это критично — SQL Server 2016+ поддерживает режим WITH (ONLINE = ON) для части операций, что сводит время блокировки к минимуму.
Универсальная схема оператора:
ALTER TABLE table_name
{operation};
Где table_name — имя существующей таблицы, operation — конкретное действие: ADD, DROP, MODIFY, ALTER COLUMN и другие.
Минимальный рабочий пример — добавление столбца в таблицу customers:
— Добавляем столбец phone в таблицу customers
ALTER TABLE customers — указываем таблицу для изменения
ADD phone VARCHAR(20) NULL; — ADD + имя столбца + тип данных + допустимость NULL
Разбор по частям:
Слово COLUMN в большинстве СУБД необязательно — ADD phone VARCHAR(20) и ADD COLUMN phone VARCHAR(20) равнозначны. Добавляйте его для читаемости кода. Синтаксис конкретной операции варьируется между СУБД: MySQL использует MODIFY COLUMN, SQL Server — ALTER COLUMN, PostgreSQL — ALTER COLUMN … TYPE … USING. Все различия разобраны в соответствующих разделах ниже.

Изменение структуры таблицы в продуктивной базе — необратимая или трудно обратимая операция. DROP COLUMN удаляет данные навсегда, изменение типа может усечь значения, а неверный порядок операций ломает зависимые объекты. Перед выполнением ALTER TABLE стоит пройти короткий чек-лист:
Зависимости столбца проверяют через системные представления. В SQL Server — через sys.columns и sys.objects, в MySQL и PostgreSQL — через INFORMATION_SCHEMA.COLUMNS:
— Проверяем, в каких таблицах есть нужный столбец (MySQL, PostgreSQL, SQL Server)
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = ‘your_database’
AND COLUMN_NAME = ‘target_column’;
В Oracle аналогичную роль играет ALL_TAB_COLUMNS. SQLite не имеет полноценного INFORMATION_SCHEMA — зависимости отслеживают вручную через PRAGMA table_info(table_name).

Добавление нового столбца — самая частая операция ALTER TABLE. Общий синтаксис одинаков во всех основных СУБД:
ALTER TABLE table_name
ADD [COLUMN] column_name data_type [constraints];
Слово COLUMN необязательно, но делает код читаемее. Ключевое поведение, которое нужно помнить: новый столбец добавляется в конец таблицы. Единственное исключение — MySQL, который поддерживает ключевые слова FIRST и AFTER для управления позицией. Все остальные СУБД — строго в конец.
Далее разбираем три сценария: добавление столбца с NULL, добавление обязательного поля в непустую таблицу и позиционирование в MySQL.
Самый простой вариант — добавить необязательное поле:
— Добавляем email в таблицу users
ALTER TABLE users
ADD email VARCHAR(255) NULL;
После выполнения у всех существующих строк в поле email будет значение NULL. Никаких дополнительных действий не требуется. Поведение одинаково во всех СУБД. Схема «до и после»:
| id |
name |
email |
|---|---|---|
| 1 | Иван | NULL |
| 2 | Мария | NULL |
Новые строки можно вставлять без указания email — столбец автоматически получит NULL:
INSERT INTO users (name) VALUES (‘Пётр’);
— В результате: id=3, name=’Пётр’, email=NULL
Если хотите сразу задать значение по умолчанию для новых строк — добавьте DEFAULT:
ALTER TABLE users
ADD email VARCHAR(255) NULL DEFAULT ‘не указан’;
Одна из самых распространённых ошибок новичков — добавить обязательное поле без DEFAULT:
— ❌ Ошибка: существующие строки не получат значения для status
ALTER TABLE orders
ADD status VARCHAR(20) NOT NULL;
— MySQL: Column ‘status’ cannot be null
— SQL Server: Cannot insert the value NULL into column ‘status’
— PostgreSQL: column «status» of relation «orders» contains null values
Правильный вариант — указать DEFAULT для существующих строк:
— ✅ Все существующие строки получат значение ‘pending’
ALTER TABLE orders
ADD status VARCHAR(20) NOT NULL DEFAULT ‘pending’;
Когда СУБД выполняет ADD NOT NULL DEFAULT, механизм такой: сначала добавляется столбец, затем все существующие строки получают значение из DEFAULT, после чего применяется ограничение NOT NULL. Без DEFAULT применить NOT NULL некуда — строки остаются без значения, и ограничение нарушается ещё до первой вставки.
SQL Server — WITH VALUES. В SQL Server ключевое слово WITH VALUES явно применяет умолчание к уже существующим строкам:
ALTER TABLE orders
ADD status VARCHAR(20) NOT NULL
CONSTRAINT df_orders_status DEFAULT ‘pending’ WITH VALUES;
Без WITH VALUES в SQL Server DEFAULT применяется только к новым строкам — существующие могут нарушить NOT NULL. Всегда указывайте WITH VALUES при добавлении NOT NULL столбца в непустую таблицу через SQL Server.
MySQL — единственная из основных СУБД, которая позволяет управлять позицией нового столбца:
— Добавить столбец в начало таблицы
ALTER TABLE users
ADD id_external INT FIRST;
— Добавить столбец после конкретного поля
ALTER TABLE users
ADD middle_name VARCHAR(100) AFTER first_name;
PostgreSQL, SQL Server и Oracle позиционирование через ALTER TABLE не поддерживают — новый столбец всегда добавляется последним. Если порядок столбцов принципиален в этих СУБД, пересоздайте таблицу через CREATE TABLE AS SELECT с нужным порядком полей. На практике порядок столбцов для запросов не важен — SELECT всегда можно написать с нужным порядком полей; визуальные инструменты типа pgAdmin или DBeaver также позволяют настроить отображение.
DROP COLUMN удаляет столбец вместе со всеми хранящимися в нём данными. Операция необратима без резервной копии:
ALTER TABLE users
DROP COLUMN middle_name;
Синтаксис одинаков в MySQL, PostgreSQL, SQL Server и Oracle. SQLite до версии 3.35.0 DROP COLUMN не поддерживает совсем — для таких случаев используется workaround с пересозданием таблицы, аналогичный описанному ниже для PRIMARY KEY.
SQL Server: после DROP COLUMN дисковое пространство не освобождается немедленно. Страницы данных продолжают занимать место на диске, пока не произойдёт перестройка кластеризованного индекса командой ALTER INDEX … REBUILD. В высоконагруженных системах это учитывают при планировании обслуживания.
Если вы изучаете SQL и хотите разобраться не только с синтаксисом ALTER TABLE, но и с проектированием баз данных с нуля, аналитикой и информационными системами в целом — в рамках федерального проекта «Активные меры содействия занятости» доступно обучение по программе «Специалист по аналитике и базам данных в информационных системах» без отрыва от работы и без вложений. Подробнее — в каталоге программ обучения.
Если на удаляемый столбец ссылается индекс, ограничение или внешний ключ — СУБД вернёт ошибку. Правильный порядок действий: сначала удалить зависимые объекты, затем сам столбец.
Пример для SQL Server — удаляем столбец email, на котором есть ограничение DEFAULT и уникальный индекс:
— Шаг 1: удаляем ограничение DEFAULT (по имени)
ALTER TABLE users
DROP CONSTRAINT df_users_email;
— Шаг 2: удаляем уникальный индекс
DROP INDEX IX_users_email ON users;
— Шаг 3: теперь удаляем столбец
ALTER TABLE users
DROP COLUMN email;
Как найти имена ограничений, если они неизвестны:
— SQL Server: список ограничений на таблице
SELECT name, type_desc
FROM sys.objects
WHERE parent_object_id = OBJECT_ID(‘users’)
AND type IN (‘D’, ‘UQ’, ‘F’, ‘PK’, ‘C’);
В MySQL несколько операций объединяют в одном ALTER TABLE — это эффективнее последовательных запросов:
— MySQL: дропаем индекс и столбец за один проход
ALTER TABLE users
DROP INDEX idx_users_email,
DROP COLUMN email;
SQLite до версии 3.35.0: DROP COLUMN не поддерживается ни в каком виде. Если версия SQLite старше — единственный путь тот же, что и для изменения PRIMARY KEY: создать новую таблицу без нужного столбца, скопировать данные, удалить старую таблицу, переименовать новую.
Изменение существующего столбца — наиболее диалектно-разнообразная операция ALTER TABLE. Ключевые слова в разных СУБД:
Операция позволяет изменить тип данных, длину строки, допустимость NULL — не трогая при этом хранящиеся значения (при условии совместимости типов).
Безопасные расширения типов — операции, при которых данные не теряются:
— INT → BIGINT: расширение диапазона, данные не теряются
— SQL Server
ALTER TABLE orders
ALTER COLUMN order_id BIGINT;
— VARCHAR(50) → VARCHAR(200): расширение длины
— MySQL
ALTER TABLE products
MODIFY COLUMN description VARCHAR(200);
— PostgreSQL
ALTER TABLE products
ALTER COLUMN description TYPE VARCHAR(200);
Сужение — другое дело. VARCHAR(200) → VARCHAR(10) приведёт к усечению строк длиннее 10 символов. СУБД либо вернёт ошибку, либо молча обрежет данные. Перед сужением убедитесь в реальных данных:
— Проверяем максимальную длину значений перед сужением (SQL Server)
SELECT MAX(LEN(description)) AS max_len FROM products;
PostgreSQL — обязательный USING. При несовместимом преобразовании типов PostgreSQL не выполнит операцию без явного указания правила конвертации через USING:
— ❌ Ошибка: PostgreSQL не может автоматически преобразовать VARCHAR → NUMERIC
ALTER TABLE orders
ALTER COLUMN total TYPE NUMERIC;
— ERROR: column «total» cannot be cast automatically to type numeric
— ✅ Правильно: указываем USING с выражением преобразования
ALTER TABLE orders
ALTER COLUMN total TYPE NUMERIC USING total::NUMERIC;
Оператор :: в PostgreSQL — синтаксический сахар для приведения типа (аналог CAST(total AS NUMERIC)). После USING можно написать любое SQL-выражение: функцию, условие, математическую операцию — это мощный инструмент для нетривиальных преобразований типов данных.
Перед изменением допустимости NULL необходимо убедиться, что в столбце нет пустых значений:
— Шаг 1: заменяем NULL на значение по умолчанию
UPDATE users
SET phone = ‘не указан’
WHERE phone IS NULL;
— Шаг 2: меняем ограничение столбца
— SQL Server
ALTER TABLE users
ALTER COLUMN phone VARCHAR(20) NOT NULL;
— MySQL
ALTER TABLE users
MODIFY COLUMN phone VARCHAR(20) NOT NULL;
— PostgreSQL — лаконичный синтаксис без повторения типа
ALTER TABLE users
ALTER COLUMN phone SET NOT NULL;
— Снятие NOT NULL в PostgreSQL
ALTER TABLE users
ALTER COLUMN phone DROP NOT NULL;
SET NOT NULL и DROP NOT NULL в PostgreSQL — удобные сокращения: не нужно повторять тип данных и другие атрибуты столбца. Без предварительного UPDATE существующие NULL нарушат ограничение — операция завершится ошибкой во всех СУБД.
Нативный синтаксис RENAME COLUMN поддерживается в MySQL 8.0+, PostgreSQL, Oracle 9i+ и SQLite 3.25+:
— MySQL 8+, PostgreSQL, Oracle 9i+, SQLite 3.25+
ALTER TABLE users
RENAME COLUMN full_name TO display_name;
Переименование таблицы:
— MySQL, PostgreSQL, SQLite
ALTER TABLE old_table_name
RENAME TO new_table_name;
— Oracle
ALTER TABLE old_table_name
RENAME TO new_table_name;
SQL Server — исключение: нативного RENAME COLUMN в T-SQL нет и никогда не было. Переименование реализуется только через системную хранимую процедуру (stored procedure) sp_rename.
sp_rename — системная хранимая процедура SQL Server для переименования объектов базы данных: таблиц, столбцов, индексов и других объектов.
— Переименование столбца: ‘таблица.старое_имя’, ‘новое_имя’, ‘COLUMN’
EXEC sp_rename ‘users.full_name’, ‘display_name’, ‘COLUMN’;
— Переименование таблицы: достаточно двух аргументов
EXEC sp_rename ‘old_table_name’, ‘new_table_name’;
— Переименование индекса
EXEC sp_rename ‘users.IX_users_email’, ‘IX_users_email_new’, ‘INDEX’;
Первый аргумент — полный путь к объекту (таблица.столбец), второй — новое имя, третий — тип объекта: ‘COLUMN’, ‘INDEX’ или ‘OBJECT’ (для таблиц и процедур).
| СУБД |
Синтаксис |
Версия |
|---|---|---|
| MySQL | ALTER TABLE t RENAME COLUMN old TO new; | 8.0+ |
| PostgreSQL | ALTER TABLE t RENAME COLUMN old TO new; | все версии |
| Oracle | ALTER TABLE t RENAME COLUMN old TO new; | 9i+ |
| SQLite | ALTER TABLE t RENAME COLUMN old TO new; | 3.25+ |
| SQL Server | EXEC sp_rename ‘table.old’, ‘new’, ‘COLUMN’; | все версии |
⚠️ После переименования столбца или таблицы обновите все зависимые объекты вручную: представления, хранимые процедуры, триггеры и прикладной код. СУБД не переименовывает ссылки автоматически — это источник трудноуловимых ошибок. В SQL Server после sp_rename система выдаёт предупреждение «Caution: Changing any part of an object name could break scripts and stored procedures» — не игнорируйте его.
Ограничения (constraints) — правила целостности данных, которые СУБД контролирует автоматически. ALTER TABLE позволяет добавлять и удалять их в уже существующих таблицах:
— Общий синтаксис именованного ограничения
ALTER TABLE table_name
ADD CONSTRAINT constraint_name constraint_type (columns);
Именованные ограничения — best practice. Автоматически сгенерированные имена типа FK__orders__user_id__3A4CA8FD неудобны в работе: сложно читать, невозможно запомнить. Используйте соглашение об именовании (naming convention): pk_ для первичных ключей, fk_ для внешних, chk_ для CHECK, uq_ для UNIQUE.
WITH CHECK (поведение по умолчанию) — проверяет ограничение на уже существующих строках при добавлении. WITH NOCHECK — добавляет ограничение только для новых строк, не проверяя существующие данные. Используется при добавлении FOREIGN KEY в таблицу с данными, которые заведомо соответствуют ограничению, — ускоряет операцию, но переносит риск на существующие данные.
— PRIMARY KEY
ALTER TABLE orders
ADD CONSTRAINT pk_orders PRIMARY KEY (order_id);
— FOREIGN KEY с явной проверкой существующих строк
ALTER TABLE orders
ADD CONSTRAINT fk_orders_user
FOREIGN KEY (user_id) REFERENCES users(id)
WITH CHECK;
— CHECK: ограничение на допустимые значения
Хотите сменить профессию или повысить квалификацию?
Федеральный проект «Активные меры содействия занятости» даёт возможность пройти обучение бесплатно за счёт государства
ALTER TABLE products
ADD CONSTRAINT chk_products_price CHECK (price > 0);
— UNIQUE: уникальность значений в столбце
ALTER TABLE users
ADD CONSTRAINT uq_users_email UNIQUE (email);
Составной PRIMARY KEY — через список столбцов:
— Составной первичный ключ из двух столбцов
ALTER TABLE order_items
ADD CONSTRAINT pk_order_items PRIMARY KEY (order_id, product_id);
— SQL Server, PostgreSQL, Oracle — универсальный синтаксис
ALTER TABLE orders
DROP CONSTRAINT fk_orders_user;
— MySQL: особый синтаксис для PRIMARY KEY и FOREIGN KEY
ALTER TABLE orders
DROP PRIMARY KEY;
ALTER TABLE orders
DROP FOREIGN KEY fk_orders_user;
— MySQL: DROP INDEX для UNIQUE-ограничений
ALTER TABLE users
DROP INDEX uq_users_email;
Как найти имя ограничения, если оно неизвестно:
— MySQL, PostgreSQL, SQL Server
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_NAME = ‘orders’
AND TABLE_SCHEMA = ‘your_database’;
В Oracle используйте USER_CONSTRAINTS или ALL_CONSTRAINTS.
Переключаясь между СУБД, легко ошибиться в синтаксисе: то, что работает в MySQL, вызывает ошибку в PostgreSQL или SQLite. Матрица ниже — быстрый справочник по поддержке 11 ключевых операций в пяти СУБД. Держите её под рукой при миграции кода между диалектами SQL.
Условные обозначения: ✅ — поддерживается нативно; ⚠️ — поддерживается с оговорками; ❌ — не поддерживается.
| Операция |
MySQL |
PostgreSQL |
SQL Server |
Oracle |
SQLite |
|---|---|---|---|---|---|
| ADD COLUMN NULL | ✅ | ✅ | ✅ | ✅ | ✅ |
| ADD COLUMN NOT NULL DEFAULT | ✅ | ✅ | ✅ WITH VALUES | ✅ | ✅ |
| DROP COLUMN | ✅ | ✅ | ✅ | ✅ | ⚠️ 3.35+ |
| MODIFY / ALTER COLUMN TYPE | ✅ MODIFY | ⚠️ USING | ✅ ALTER COLUMN | ✅ MODIFY | ❌ |
| ALTER COLUMN NULL/NOT NULL | ✅ | ✅ SET/DROP | ✅ | ✅ | ❌ |
| RENAME COLUMN | ✅ 8.0+ | ✅ | ❌ → sp_rename | ✅ 9i+ | ✅ 3.25+ |
| RENAME TABLE | ✅ | ✅ | ❌ → sp_rename | ✅ | ✅ |
| ADD PRIMARY KEY | ✅ | ✅ | ✅ | ✅ | ❌ workaround |
| ADD FOREIGN KEY | ✅ | ✅ | ✅ | ✅ | ⚠️ синтаксис есть, не применяется |
| ADD CHECK | ✅ | ✅ | ✅ | ✅ | ⚠️ синтаксис есть, не применяется |
| ONLINE-режим | ⚠️ InnoDB | ❌ | ✅ 2016+ | ❌ | ❌ |
Вывод из матрицы: SQLite — наиболее ограниченная СУБД по возможностям ALTER TABLE; SQL Server — наиболее расширенная за счёт ONLINE-операций и гибкого sp_rename. Всегда проверяйте версию СУБД перед использованием новых возможностей: поведение SQLite принципиально меняется на версиях 3.25 (появляется RENAME COLUMN) и 3.35 (появляется DROP COLUMN).
Стандарт SQL-92 определяет базовый синтаксис ALTER TABLE, но каждый диалект SQL добавляет собственные расширения — и собственные ограничения. В этом разделе — ключевые особенности пяти СУБД, которые нужно знать при написании реального кода.
Добавление NOT NULL столбца в непустую таблицу:
ALTER TABLE orders
ADD created_at DATETIME NOT NULL
CONSTRAINT df_orders_created_at DEFAULT GETDATE() WITH VALUES;
GETDATE() — встроенная функция T-SQL, возвращающая текущую дату и время. WITH VALUES применяет DEFAULT ко всем существующим строкам.
ALTER COLUMN с ONLINE-режимом — SQL Server 2016+:
— Изменение типа с минимальной блокировкой таблицы
ALTER TABLE large_table
ALTER COLUMN description VARCHAR(500)
WITH (ONLINE = ON);
ONLINE = ON — блокировка действует только в самом начале и конце операции (короткие Sch-M). Таблица остаётся доступной для чтения и записи почти всё время. Без ONLINE = ON блокировка длится всю операцию — для таблиц с миллионами строк это может занять минуты.
RENAME — только через sp_rename:
— Переименование столбца
EXEC sp_rename ‘orders.created_at’, ‘order_date’, ‘COLUMN’;
— Переименование таблицы
EXEC sp_rename ‘orders’, ‘customer_orders’;
Ограничения ALTER COLUMN в SQL Server:
MySQL использует MODIFY COLUMN вместо ALTER COLUMN:
— Изменение типа, размера и ограничений
ALTER TABLE products
MODIFY COLUMN price DECIMAL(10,2) NOT NULL DEFAULT 0.00;
С MySQL 8.0 доступен нативный RENAME COLUMN — без sp_rename и без пересоздания таблицы:
ALTER TABLE users
RENAME COLUMN full_name TO display_name;
Сила MySQL — возможность объединять несколько операций в одном ALTER TABLE. Таблица перестраивается один раз вместо N раз:
— Четыре операции за один проход
ALTER TABLE users
ADD COLUMN avatar_url VARCHAR(500) NULL AFTER email,
MODIFY COLUMN email VARCHAR(320) NOT NULL,
RENAME COLUMN phone TO phone_number,
ADD INDEX idx_users_email (email);
Позиционирование нового столбца — только в MySQL:
ALTER TABLE users
ADD COLUMN profile_id INT FIRST; — в начало
ALTER TABLE users
ADD COLUMN bio TEXT AFTER display_name; — после конкретного поля
PostgreSQL позволяет изменять тип данных через ALTER COLUMN … TYPE, но при несовместимом преобразовании требует явного USING:
— Преобразование VARCHAR → INTEGER с кастом через ::
ALTER TABLE logs
ALTER COLUMN status_code TYPE INTEGER USING status_code::INTEGER;
— Более сложное преобразование с функцией
ALTER TABLE users
ALTER COLUMN birth_date TYPE DATE
USING TO_DATE(birth_date, ‘DD.MM.YYYY’);
Лаконичные команды для управления допустимостью NULL:
— Установить NOT NULL
ALTER TABLE users
ALTER COLUMN email SET NOT NULL;
— Снять NOT NULL
ALTER TABLE users
ALTER COLUMN phone DROP NOT NULL;
PostgreSQL не поддерживает WITH NOCHECK для FOREIGN KEY. При добавлении FK все существующие строки проверяются автоматически — если есть нарушения, операция завершится ошибкой. Также нет ONLINE-режима: блокировка при изменении типа держится всё время операции.
Oracle использует MODIFY без слова COLUMN:
— Изменение типа данных
ALTER TABLE employees
MODIFY salary NUMBER(12,2);
— Изменение допустимости NULL
ALTER TABLE employees
MODIFY department_id NOT NULL;
— Изменение нескольких столбцов одновременно
ALTER TABLE employees
MODIFY (
first_name VARCHAR2(100),
last_name VARCHAR2(100)
);
RENAME COLUMN доступен с Oracle 9i:
ALTER TABLE employees
RENAME COLUMN emp_no TO employee_id;
Ограничение Oracle: нельзя удалить единственный столбец таблицы. Если таблица состоит из одного поля, сначала добавьте вспомогательный столбец, затем удалите нужный. Для удаления нескольких столбцов одновременно Oracle поддерживает компактный синтаксис:
ALTER TABLE employees
DROP (department_id, manager_id);
SQLite поддерживает ограниченный набор операций ALTER TABLE:
FOREIGN KEY и CHECK в SQLite принимаются синтаксически при CREATE TABLE, но при ALTER TABLE ADD CONSTRAINT работать не будут — только workaround через пересоздание таблицы.
— ❌ Ошибка: NOT NULL без DEFAULT в непустой таблице SQLite
ALTER TABLE users ADD age INTEGER NOT NULL;
— ✅ Правильно
ALTER TABLE users ADD age INTEGER NOT NULL DEFAULT 0;
Workaround для PRIMARY KEY — 4 шага:
SQLite не позволяет добавить PRIMARY KEY через ALTER TABLE — это фундаментальное ограничение архитектуры. Единственный путь — пересоздать таблицу:
— Шаг 1: создаём новую таблицу с нужной структурой и PRIMARY KEY
CREATE TABLE users_new (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT
);
— Шаг 2: копируем данные из старой таблицы
INSERT INTO users_new (id, name, email)
SELECT id, name, email FROM users;
— Шаг 3: удаляем старую таблицу
DROP TABLE users;
— Шаг 4: переименовываем новую таблицу
ALTER TABLE users_new RENAME TO users;
Этот подход применяется для любых структурных изменений, которые SQLite не поддерживает через ALTER TABLE: изменение типа столбца, добавление/удаление ограничений, изменение PRIMARY KEY. Рекомендуется обернуть все четыре шага в транзакцию (BEGIN TRANSACTION / COMMIT), чтобы при сбое данные не оказались в промежуточном состоянии.

Большинство ошибок ALTER TABLE — типовые: их допускают снова и снова при переходе между СУБД или при работе с непустыми таблицами. Разбираем пять наиболее распространённых.
Ошибка 1: ADD NOT NULL без DEFAULT
— ❌ Ошибка: существующие строки не получат значения для priority
ALTER TABLE orders ADD priority VARCHAR(10) NOT NULL;
— MySQL: Column ‘priority’ cannot be null
— SQL Server: Cannot insert the value NULL into column ‘priority’
— ✅ Решение: задать DEFAULT для существующих строк
ALTER TABLE orders ADD priority VARCHAR(10) NOT NULL DEFAULT ‘normal’;
Причина: при добавлении столбца СУБД «смотрит» на существующие строки. Если значение поставить некуда, ограничение NOT NULL нарушается немедленно, ещё до первой вставки новых данных.
Ошибка 2: DROP COLUMN с зависимостями
— ❌ Ошибка: на столбце есть уникальный индекс
ALTER TABLE users DROP COLUMN email;
— SQL Server: The object ‘IX_users_email’ is dependent on column ’email’
— PostgreSQL: column «email» of relation «users» cannot be dropped because other objects depend on it
— ✅ Решение: сначала зависимые объекты, потом столбец
ALTER TABLE users DROP CONSTRAINT uq_users_email;
DROP INDEX IX_users_email ON users; — SQL Server
ALTER TABLE users DROP COLUMN email;
Порядок всегда такой: DROP CONSTRAINT → DROP INDEX → DROP COLUMN. Нарушение порядка даёт ошибку зависимости.
Ошибка 3: RENAME COLUMN в SQL Server без sp_rename
— ❌ SQL Server не поддерживает нативный RENAME COLUMN
ALTER TABLE users RENAME COLUMN old_email TO email_address;
— Incorrect syntax near ‘RENAME’
— ✅ Только через sp_rename
EXEC sp_rename ‘users.old_email’, ’email_address’, ‘COLUMN’;
Ошибка 4: PostgreSQL без USING при несовместимых типах
— ❌ PostgreSQL не выполнит преобразование без USING
ALTER TABLE logs ALTER COLUMN status_code TYPE INTEGER;
— ERROR: column «status_code» cannot be cast automatically to type integer
— ✅ Добавляем USING с правилом преобразования
ALTER TABLE logs
ALTER COLUMN status_code TYPE INTEGER
USING status_code::INTEGER;
Ошибка 5: ADD PRIMARY KEY в SQLite
— ❌ SQLite не поддерживает ADD CONSTRAINT ни в каком виде
ALTER TABLE users ADD CONSTRAINT pk_users PRIMARY KEY (id);
— ParseError: near «CONSTRAINT»: syntax error
— ✅ Только workaround: CREATE TABLE новая → INSERT → DROP старая → RENAME
— Полный код — в разделе про SQLite выше
Помимо синтаксических ошибок встречаются и логические: изменение типа столбца без предварительной проверки реальных данных, удаление столбца, на который ссылается прикладной код, или переименование без обновления хранимых процедур. Любая из этих ситуаций нарушает работу приложения — поэтому тест на dev-базе перед ALTER TABLE на продуктиве обязателен всегда.
MySQL использует MODIFY COLUMN, SQL Server — ALTER COLUMN, PostgreSQL — ALTER COLUMN TYPE с обязательным USING при несовместимых преобразованиях. Переименование столбца в SQL Server выполняется только через sp_rename; в остальных СУБД — нативный RENAME COLUMN. MySQL позволяет задавать позицию нового столбца через FIRST / AFTER, другие СУБД добавляют столбец строго в конец. MySQL также позволяет объединять несколько операций в одном запросе — таблица перестраивается один раз.
Напрямую нельзя — SQLite не поддерживает ADD CONSTRAINT. Workaround из четырёх шагов: 1) создать новую таблицу с нужным PRIMARY KEY через CREATE TABLE; 2) скопировать данные через INSERT INTO new_t SELECT * FROM old_t; 3) удалить старую таблицу DROP TABLE old_t; 4) переименовать новую через ALTER TABLE new_t RENAME TO old_t. Все четыре шага рекомендуется выполнять в одной транзакции.
Безопасные расширения — INT→BIGINT, VARCHAR(50)→VARCHAR(200) — данные не теряются. Сужение типа или диапазона грозит усечением. В PostgreSQL при несовместимых типах обязателен USING: ALTER COLUMN col TYPE NUMERIC USING col::NUMERIC. В SQLite изменение типа данных столбца через ALTER TABLE не поддерживается вообще — нужен workaround с пересозданием таблицы. Перед изменением типа всегда проверяйте реальный диапазон значений в столбце и делайте резервную копию.
sp_rename — системная хранимая процедура SQL Server для переименования объектов базы данных. Синтаксис для столбца: EXEC sp_rename ‘TableName.OldCol’, ‘NewCol’, ‘COLUMN’;. Она необходима потому, что SQL Server не поддерживает нативный RENAME COLUMN в операторе ALTER TABLE — в отличие от MySQL 8+, PostgreSQL и Oracle 9i+. После вызова sp_rename система выдаёт предупреждение о необходимости обновить зависимые объекты.
Данные удаляются безвозвратно. В SQL Server дисковое пространство не освобождается немедленно — нужна перестройка кластеризованного индекса через ALTER INDEX … REBUILD. В SQLite до версии 3.35.0 DROP COLUMN не поддерживается совсем — нужен workaround с пересозданием таблицы. Перед удалением убедитесь в отсутствии зависимых индексов, ограничений и прикладного кода, который обращается к этому столбцу.
Обязательно указывайте DEFAULT: ALTER TABLE t ADD col VARCHAR(50) NOT NULL DEFAULT ‘value’;. Без DEFAULT существующие строки не получат значений — ограничение NOT NULL нарушается до первой вставки, и операция завершится ошибкой. В SQL Server дополнительно укажите WITH VALUES, чтобы DEFAULT применился к уже существующим строкам, а не только к новым.
В SQL Server 2016+ используйте ALTER COLUMN … WITH (ONLINE = ON) — таблица остаётся доступной почти всё время, короткая Sch-M-блокировка накладывается лишь в начале и конце операции. MySQL InnoDB поддерживает часть операций в онлайн-режиме, но не все. PostgreSQL и SQLite по умолчанию блокируют таблицу на всё время операции — планируйте их на период низкого трафика.
Сначала обновите строки с NULL-значениями: UPDATE t SET col = ‘default_value’ WHERE col IS NULL;. Затем примените ограничение: в SQL Server — ALTER TABLE t ALTER COLUMN col VARCHAR(50) NOT NULL;, в MySQL — MODIFY COLUMN col VARCHAR(50) NOT NULL;, в PostgreSQL — ALTER TABLE t ALTER COLUMN col SET NOT NULL;. Без предварительного UPDATE операция завершится ошибкой — существующие NULL нарушат ограничение.
Подайте заявку —
забронируйте место в группе
45 000 мест на 2026 год. Бесплатное обучение по федеральному проекту «Активные меры содействия занятости»