如何复制表格的结构和内容,但顺序不同?

Posted

技术标签:

【中文标题】如何复制表格的结构和内容,但顺序不同?【英文标题】:How to copy structure and contents of a table, but with separate sequence? 【发布时间】:2012-08-29 04:27:55 【问题描述】:

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

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,因此在插入时将其递增。有没有一种简单的方法来创建具有自己序列的新表,还是我必须手动设置一个新序列?

【问题讨论】:

【参考方案1】:

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

db小提琴here

相关:

How to reset postgres' primary key sequence when it falls out of sync? Is there a shortcut for SELECT * FROM? Creating a PostgreSQL sequence to a field (which is not the ID of the record)

原始(旧)答案

您可以从数据库转储或pgAdmin 之类的 GUI(它对数据库对象创建脚本进行逆向工程)获取创建脚本,创建一个相同的副本(serial 列具有单独的序列),然后运行:

INSERT INTO new_tbl
SELECT * FROM old_tbl;

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

将副本放在不同的架构中可以避免所有这些冲突。当您像演示的那样从 常规 表创建 临时 表时,由于临时表驻留在它们自己的临时模式中,因此情况自动发生。

或者直接看Francisco's answer的DDL代码复制。

【讨论】:

【参考方案2】:

我正在使用以下代码:

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;

【讨论】:

这是最好的答案,IMO。给你你想要的! 要使serial 列完整,该序列应由该列拥有ALTER SEQUENCE t_mytable_id_seq OWNED BY t_mytable.id; 感谢@ErwinBrandstetter。我将您的句子包含在答案中。

以上是关于如何复制表格的结构和内容,但顺序不同?的主要内容,如果未能解决你的问题,请参考以下文章

ABAP 中内表的复制

如何用VBA新建一个EXCEL表,并将将另一个EXCEL表中的内容复制到这个新建的EXCEL表中

将 mySql 数据库表复制到另一个具有不同表结构的数据库表

excel表怎么把2个表相同的表头不同的内容合并在一起?

如何控制复制到剪贴板的文本

修改复制表结构