使用SQL完全复制postgres表

Eri*_*rik 68 sql postgresql data-migration

免责声明:这个问题类似于这里的堆栈溢出问题,但这些答案都不适合我的问题,我稍后会解释.

我正在尝试在postgres中复制一个大表(大约40M行,100多列),其中很多列都被索引.目前我使用这个SQL:

CREATE TABLE <tablename>_copy (LIKE <tablename> INCLUDING ALL);
INSERT INTO <tablename>_copy SELECT * FROM <tablename>;
Run Code Online (Sandbox Code Playgroud)

这种方法有两个问题:

  1. 它在数据摄取之前添加索引,因此比创建没有索引的表需要更长的时间,然后在复制所有数据后进行索引.
  2. 这不会正确复制`SERIAL'样式列.它不是在新表上设置新的"计数器",而是将新表中列的默认值设置为过去表的计数器,这意味着它不会随着行的添加而增加.

表大小使索引成为实时问题.它还使得转储到文件然后重新摄取是不可行的.我也没有命令行的优势.我需要在SQL中执行此操作.

我想要做的是直接用一些奇迹命令制作一个精确的副本,或者如果那是不可能的话,复制具有所有约束但没有索引的表,并确保它们是精神上的约束'(又名) SERIAL列的新计数器).然后用a复制所有数据,SELECT *然后复制所有索引.

来源

  1. 关于数据库复制的Stack Overflow问题:由于三个原因,这不是我要求的

    • 它使用命令行选项pg_dump -t x2 | sed 's/x2/x3/g' | psql,在此设置中,我无权访问命令行
    • 它创建索引前数据摄取,这很慢
    • 它没有正确更新串行列作为证据 default nextval('x1_id_seq'::regclass)
  2. 重置postgres表的序列值的方法:这很好,但不幸的是它非常手动.

Phi*_*ill 60

create table asPostgreSQL中的功能现在可能是OP正在寻找的答案.

https://www.postgresql.org/docs/9.5/static/sql-createtableas.html

create table my_table_copy as
  select * from my_table
Run Code Online (Sandbox Code Playgroud)

这将创建一个与数据相同的表.

添加with no data将复制没有数据的架构.

create table my_table_copy as
  select * from my_table
with no data
Run Code Online (Sandbox Code Playgroud)

这将创建包含所有数据的表,但没有索引和触发器等.


create table my_table_copy (like my_table including all)

create table like语法将包括所有触发器,索引,约束等.但不包括数据.

  • 我很久以前就发布了这个问题,以至于我没有简便的方法可以轻松地对此进行验证。但是,“创建表为”似乎并不复制与该表关联的其他对象,例如索引和序列。 (3认同)

Sco*_*owe 59

好吧,不幸的是,你将不得不亲手做一些这样的事情.但它可以从像psql这样的东西完成.第一个命令很简单:

select * into newtable from oldtable
Run Code Online (Sandbox Code Playgroud)

这将使用oldtable的数据而不是索引创建newtable.然后你必须自己创建索引和序列等.您可以使用以下命令获取表上所有索引的列表:

select indexdef from pg_indexes where tablename='oldtable';
Run Code Online (Sandbox Code Playgroud)

然后运行psql -E来访问你的数据库并使用\ d来查看旧表.然后,您可以修改这两个查询以获取序列的信息:

SELECT c.oid,
  n.nspname,
  c.relname
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname ~ '^(oldtable)$'
  AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 2, 3;

SELECT a.attname,
  pg_catalog.format_type(a.atttypid, a.atttypmod),
  (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
   FROM pg_catalog.pg_attrdef d
   WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef),
  a.attnotnull, a.attnum
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = '74359' AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum;
Run Code Online (Sandbox Code Playgroud)

将上面的74359替换为您从上一个查询中获得的oid.


Pet*_*aut 14

最接近的"奇迹命令"就像是

pg_dump -t tablename | sed -r 's/\btablename\b/tablename_copy/' | psql -f -
Run Code Online (Sandbox Code Playgroud)

特别是,这需要在加载表数据后创建索引.

但这不会重置序列; 你必须自己编写脚本.


K M*_*lam 7

要完全复制一个表,包括表结构和数据,请使用以下语句:

CREATE TABLE new_table AS 
TABLE existing_table;
Run Code Online (Sandbox Code Playgroud)

要复制不包含数据的表结构,可以将WITH NO DATA子句添加到CREATE TABLE语句中,如下所示:

CREATE TABLE new_table AS 
TABLE existing_table 
WITH NO DATA;
Run Code Online (Sandbox Code Playgroud)

要从现有表复制包含部分数据的表,请使用以下语句:

CREATE TABLE new_table AS 
SELECT
*
FROM
    existing_table
WHERE
    condition;
Run Code Online (Sandbox Code Playgroud)