如何复制表的结构和内容,但具有单独的顺序?

时间:2012-09-04 13:38:04

标签: sql postgresql temp-tables create-table

我正在尝试设置临时表以进行单元测试。到目前为止,我设法创建了一个复制现有表结构的临时表:

CREATE TEMP TABLE t_mytable (LIKE mytable INCLUDING DEFAULTS);

但这缺乏原始表中的数据。我可以使用CREATE TABLE AS语句将数据复制到临时表中:

CREATE TEMP TABLE t_mytable AS SELECT * FROM mytable;

但是t_mytable的结构将不相同,例如列大小和默认值不同。是否有一个复制所有内容的声明?

使用LIKE的第一个查询的另一个问题是,键列仍然引用原始表的SEQUENCE,因此在插入时会增加它。是否有一种简单的方法来创建具有自己序列的新表,或者我是否必须手动设置新序列?

2 个答案:

答案 0 :(得分:26)

我正在使用以下代码执行此操作:

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;

答案 1 :(得分:7)

Postgres 10或更高版本

Postgres 10引入符合SQL标准的IDENTITY columns(带有次要扩展)。表格的ID列如下所示:

id    integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY

Syntax in the manual.
使用此列而不是传统的serial列可以避免序列问题。即使使用IDENTITY复制规范,LIKE列也会自动使用专用的专用序列。 The manual:

  

复制列定义的任何标识规范都只是   如果指定INCLUDING IDENTITY则复制。创建一个新序列   对于新表的每个标识列,与序列分开   与旧桌子相关联。

  

INCLUDING ALLINCLUDING 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()获取序列的名称。

db<>小提琴here

相关:


原始(旧)回答

您可以从数据库转储或GUI pgAdmin(反向工程数据库对象创建脚本)中创建创建脚本,创建相同的副本(serial列的单独序列) ,然后运行:

INSERT INTO new_tbl
SELECT * FROM old_tbl;

如果两个表都位于同一模式中,则副本不能100%相同。显然,表名必须不同。索引名称也会发生冲突。从同一序列中检索序列号可能也不符合您的最佳利益。所以你必须(至少)调整名称。

将副本放在不同的模式中可以避免所有这些冲突。当您从演示的常规表创建临时表时,由于临时表驻留在它们自己的临时模式中,所以这是自动的。

或者查看Francisco's answer以便直接复制DDL代码。