В миграции PostgreSQL нужно получить пустую таблицу с текущей структурой исходной. Какую связь между таблицами создаст команда LIKE?
CREATE SCHEMA ops;
CREATE TABLE ops.source (
id INTEGER PRIMARY KEY,
payload TEXT NOT NULL DEFAULT ''
);
CREATE TABLE ops.stage (
LIKE ops.source INCLUDING ALL
);
Команда CREATE TABLE ... LIKE создаёт новую независимую таблицу, копируя структуру исходной; строки исходной таблицы не переносятся. Между ops.source и ops.stage не возникает автоматической зависимости: последующие изменения исходной таблицы не изменят структуру stage.
INCLUDING ALL в PostgreSQL запрашивает копирование доступных атрибутов структуры, включая ограничения и индексы. Точный состав копируемых свойств зависит от диалекта и версии СУБД, поэтому такую конструкцию нельзя без проверки переносить между разными SQL-системами.
Механизм LIKE появился как средство повторного использования структуры таблиц без ручного дублирования списка столбцов, типов и ограничений. Это особенно полезно для временных рабочих таблиц, staging-таблиц, архивов и тестовых объектов.
Без такого механизма разработчику пришлось бы вручную поддерживать две версии DDL. Однако LIKE решает только задачу копирования структуры в момент выполнения команды, а не задачу синхронизации схем в будущем.
Если разработчик ожидает, что ops.stage будет автоматически следовать изменениям ops.source, он выберет неподходящий механизм. Например, добавление нового столбца в source не добавит его в stage, а изменение ограничения исходной таблицы не изменит уже созданную копию.
Есть и риск ошибочно считать копию полностью независимой. Скопированные выражения DEFAULT могут ссылаться на внешние объекты, а скопированные индексы и ограничения становятся отдельными объектами, но требуют проверки на соответствие назначению новой таблицы.
LIKE читается как создание таблицы на основе описания другой таблицы. СУБД анализирует структуру ops.source и формирует для ops.stage собственные столбцы и, при указании соответствующих опций, собственные ограничения, индексы и другие свойства.
После выполнения CREATE TABLE таблица stage пуста. Она не является представлением, синонимом или ссылкой на source; запрос к stage не читает строки из source.
Ключевое отличие от представления состоит в том, что представление хранит описание запроса и обычно вычисляет результат при обращении, а LIKE создаёт физическую таблицу с собственной структурой и собственными данными.
Опция INCLUDING ALL удобна, когда нужна максимально полная копия определения, но она не означает копирование данных и не гарантирует перенос всех семантических связей. Нужно отдельно проверить внешние ключи, права доступа, триггеры, политики, комментарии, последовательности и особенности конкретной СУБД.
Особое внимание требуется уделять значениям по умолчанию. Если скопированное выражение DEFAULT явно обращается к существующему объекту, например к последовательности, новая таблица может использовать тот же объект, а не автоматически получить отдельный. Для независимой генерации идентификаторов это следует проверить по документации и системному каталогу PostgreSQL.
Преимущество подхода — короткий и поддерживаемый DDL. Компромисс — зависимость от диалекта, неочевидное копирование некоторых объектов и отсутствие последующей синхронизации структуры.
Команде понадобилась staging-таблица для загрузки заказов перед проверкой. Рассматривались три варианта: CREATE TABLE AS SELECT, ручное перечисление столбцов и CREATE TABLE ... LIKE.
CREATE TABLE AS SELECT удобно для одновременного получения данных, но обычно не переносит полную систему ограничений и индексов. Ручной DDL даёт полный контроль, однако легко устаревает при изменении исходной таблицы.
Выбрали LIKE для первоначального создания пустой staging-таблицы, затем явно добавили только нужные для загрузочного процесса индексы и ограничения. После этого миграции изменяли обе схемы осознанно, потому что автоматической синхронизации между таблицами нет.
Переносит ли LIKE данные исходной таблицы?
Нет. LIKE копирует определение таблицы, но не строки. Для переноса данных нужна отдельная команда, например INSERT INTO ... SELECT ..., либо другой механизм загрузки. Поэтому новая таблица сразу после создания остаётся пустой.
Станет ли скопированный индекс общим для двух таблиц?
Нет. Если PostgreSQL создаёт индекс для новой таблицы через соответствующую опцию LIKE, это отдельный индекс, обслуживающий только новую таблицу. Изменение или удаление индекса на исходной таблице не изменяет индекс копии.
Гарантирует ли INCLUDING ALL полную независимость новой таблицы от всех объектов исходной?
Нет. Он копирует набор поддерживаемых свойств структуры, но не превращает каждый объект, на который ссылаются выражения или настройки, в отдельную копию. Например, DEFAULT может содержать ссылку на уже существующую последовательность или функцию. Поэтому после создания нужно проверить зависимости системного каталога и при необходимости явно создать отдельные последовательности, триггеры, права и внешние связи.