将一个 table 中缺失的记录复制到一个新的 table

Copy records missing from one table to a new table

我设法从我的 129,000 行生产数据库(Heroku 上的 Postgres 9.4)中的 table 中删除了 4,000 行,但几天后才发现问题。

我有丢失前的备份,但只想选择性地将丢失的行恢复到table,保留它们的 ID。 (完全恢复不是一个选项,因为新数据已经添加到 table。)

我将备份的 table 作为 articles_backup 与实际的 articles table 一起导入到本地测试数据库中。我想在 articles_backups 中找到 articles 中丢失的所有行,然后将它们复制到新的 table articles_restores 中,然后我将恢复到生产数据库,返回进入 articles table(保留记录 ID)。

查询成功returns所有删除记录的id:

select articles_backups.id
from articles_backups
left outer join articles on (articles_backups.id = articles.id)
where articles.id is null

但我无法将结果复制到新的 table。我试过没有成功:

select *
into articles_restores
from articles_backups
left outer join articles on (articles_backups.id = articles.id)
where articles.id is null;

给出:

ERROR:  column "id" specified more than once

您可以使用 except 检索 articles_backup 中不同于 articles 的所有行:

(假设两个表具有相同顺序的相同列)

您还可以 create a temp table 使用此信息来简化您的维修报表:

create table temp_articles as
select * from articles_backup 
except
select * from articles

第 1 步 - 更新 articles 中 'articles_backup' 的行。

这一步需要注意...您必须建立一个规则来在 articlestemp_articles 中的数据之间进行选择。

UPDATE articles a
SET a.col1=b.col1,
    a.col2=b.col2,
    (... other columns ...)
FROM (SELECT * FROM  temp_articles) AS b
WHERE a.id = b.id and /* your rule for data to be (or not) updated goes here */

第 2 步 - 插入 'articles_backup' 中不存在于 articles 中的行(您已删除的记录):

insert into articles
select * from temp_articles where id not in (select id from articles)

如果您需要更多帮助,请告诉我们。

基本上,您使用 LEFT JOIN / IS NULL 的查询会满足您的要求:

  • Select rows which are not present in other table

您收到错误是因为您 select 来自两个 table 的所有列,并且两者中都有一个 id 列。无法创建具有重复列名的新 table,这不是您想要的开头。只有 select 列来自 articles_backups:

CREATE TABLE articles_restores AS
SELECT <b>ab.*</b>
FROM   articles_backups ab
LEFT   JOIN articles a USING (id)
WHERE  a.id IS NULL;

我使用 table 别名简化了您的查询语法。 USING 子句只是为了方便缩短代码。它将两个 id 列折叠成一个,但如果您 SELECT *.

所有其他列仍然在那里两次

使用CREATE TABLE ASSELECT INTO 也由 SQL 标准定义并在 Postgres 中实现,但不鼓励使用它。它在 PL/pgSQL 函数中用于不同的目的。详情:

  • Creating temporary tables in SQL