Как скопировать структуру и содержимое таблицы PostgreSQL, но дублировать последовательности?

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

CREATE TEMP TABLE t_mytable (LIKE mytable INCLUDING DEFAULTS);

но этого не хватает данных из исходной таблицы. Я могу скопировать данные во временную таблицу с помощью инструкции:

CREATE TEMP TABLE t_mytable AS SELECT * FROM mytable;

но тогда strucutre из t_mytable не будет идентичным, например, размеры столбцов и значения по умолчанию различны. Есть один оператор который копирует все?

еще одна проблема, с которой я сталкиваюсь с первым запросом, используя LIKE является то, что ключевое поле ссылается на последовательность ID исходной таблицы и, таким образом, увеличивает ее при вставке. Есть ли простой способ дублировать последовательности для таблицы модульного тестирования, или мне придется настраивать новые последовательности вручную?

2 ответов


Postgres 10 или позже

Postgres 10 представил IDENTITY колонки в соответствии со стандартом SQL (с незначительными расширениями). Столбец ID вашей таблицы будет выглядеть примерно так:

id    integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY

синтаксис в руководстве.
Используя это вместо традиционного serial столбец избегает вашей проблемы с последовательностями. IDENTITY столбцы используют эксклюзивные, выделенные последовательности автоматически, даже когда спецификация копируется с помощью LIKE. инструкции:

любые спецификации идентичности скопированных определений столбцов будут только скопировано if это. Создается новая последовательность для каждого столбца идентификаторов новой таблицы, отдельно от последовательности связано со старой таблицей.

и:

INCLUDING ALL является сокращенной формой INCLUDING DEFAULTS INCLUDING IDENTITY INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS.

в решение сейчас проще:

CREATE TEMP TABLE t_mytable (LIKE mytable INCLUDING ALL);
INSERT INTO t_mytable TABLE mytable;
SELECT setval(pg_get_serial_sequence('t_mytable', 'id'), max(id)) FROM tbl;

как показано, вы можете использовать setval() для установки текущего значения последовательностей. Один SELECT делает трюк. Использовать pg_get_serial_sequence() чтобы получить имя последовательности.

dbfiddle здесь

по теме:


оригинальный (старый) ответ

вы можете взять сценарий создания из дампа базы данных или GUI, как pgAdmin попробуйте (который реверс-проектирует сценарии создания объекта базы данных), создайте идентичную копию (с отдельной последовательностью для


Я использую для этого следующий код:

CREATE TABLE t_mytable (LIKE mytable INCLUDING ALL);
ALTER TABLE t_mytable ALTER id DROP DEFAULT;
CREATE SEQUENCE t_mytable_id_seq;
INSERT INTO t_mytable SELECT * FROM mytable;
SELECT setval('t_mytable_id_seq', (SELECT max(id) FROM t_mytable), true);
ALTER TABLE t_mytable ALTER id SET DEFAULT nextval('t_my_table_id_seq');
ALTER SEQUENCE t_mytable_id_seq OWNED BY t_mytable.id;