使用psql和--disable-triggers恢复纯文本pg_dump


8

我必须使用一个简短的脚本执行一些测试,以更新我的一张表中的某些“旧版”数据。

我非常谨慎,我使用未经测试的脚本决定先备份相关表。最简单的方法是:

pg_dump -a --file table.sql -t table database

现在我做了我必须做的,检查了结果,发现它们不尽人意。我对自己说:我很幸运能得到那张桌子的备份。

备份表时已经警告过我:

pg_dump: NOTICE: there are circular foreign-key constraints among these table(s):
pg_dump:   table
pg_dump: You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints.
pg_dump: Consider using a full dump instead of a --data-only dump to avoid this problem.

我没怎么想,但现在我们遇到了问题。确实,有问题的表已附加了多个触发器,但是我无法还原 pg_restore命令的table.sqlwith选项--disable-triggers

如果我尝试执行以下命令,则会收到错误消息:

pg_restore -a -d database -t table -h localhost --disable-triggers table.sql

即:

pg_restore: [archiver] input file appears to be a text format dump. Please use psql.

psql-command 是否有一个标志与它表现出相同的行为--disable-triggers

我已经检查了psql“ manpage”,搜索触发器和类似的关键字,但是什么也没找到。

还是在还原数据之前我必须将触发器放在表上的唯一选择?

旁注:我在Ubuntu 14.10系统上使用Postgres v。9.3


建议编辑生成的sql文件,使其包含以下语句:

ALTER TABLE table DISABLE TRIGGER ALL

现在执行时:psql -d database -f table.sql我收到一条有关违反主键的“唯一”约束的错误消息。

为了解决这个问题,我尝试将副本包装到:

BEGIN TRANSACTION READ WRITE;
TRUNCATE TABLE table;

-- copy here

COMMIT;

现在错误消息是:

psql:project_backup.sql:18: ERROR:  cannot truncate a table referenced in a foreign key constraint
DETAIL:  Table "another" references "table".
HINT:  Truncate table "another" at the same time, or use TRUNCATE ... CASCADE.
psql:project_backup.sql:20: ERROR:  current transaction is aborted, commands ignored until end of transaction block
psql:project_backup.sql:21: invalid command \N
psql:project_backup.sql:22: invalid command \N

对于\N转储中的每个警告(表示空值),都会重复执行后一个警告。


2
您可以在任何编辑器中编辑转储。只要预先设置COPYALTER TABLE table DISABLE TRIGGER ALL,并在年底重新启用这些。
dezso 2015年

仅在禁用之前,我收到一条错误消息,指出副本违反了主键的唯一约束。(完全可以理解)当我继续BEGIN TRANSACTION READ WRITE; TRUNCATE TABLE table;确保数据安全时,我收到有关无效命令的消息:(
Vogel612,2015年

@ Vogel612“无效命令”?请显示确切的错误。
Craig Ringer

@CraigRinger抱歉,等待,我编辑了问题,以包括我做了什么以及收到的错误消息
Vogel612

所有这些都意味着一些数据已经更新,对吗?尝试使用临时表在其中复制原始数据的方式将它们更新回来。
dezso 2015年

Answers:


4

@dezso有一个完全正确的想法

所有这些都意味着一些数据已经更新,对吗?尝试使用临时表在其中复制原始数据的方式将它们更新回来

现在剩下的唯一事情就是实现它。

这就是我所做的。我从他的书中拿出一片叶子,并手动编辑了转储文件以使用名为的表table_backup。然后,我使用pgAdmin中提供的定义创建了所说的表(但是也可以手动完成)。

我省略了触发器和约束以及外键,然后使用备份表中的数据来“更新”原始表,如下所示:

BEGIN TRANSACTION;
ALTER TABLE table DISABLE TRIGGER ALL;

UPDATE table SET 
    (column1, column2, ...) = 
    (table_backup.column1, table_backup.colum2, ...)
FROM table_backup WHERE table.pk_column = table_backup.pk_column;

ALTER TABLE table ENABLE TRIGGER ALL;
-- I didn't but you can drop table_backup here
COMMIT;

所以我终于回到了原始数据,准备进行下一次测试;)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.