使用PostgreSQL 9.2.8,我试图将我的数据从一个数据库恢复到另一个数据库,但触发器似乎仍在运行。我已经编写了如下所示的脚本来进行复制。
基本上我有dts
作为我的生产数据库,我有DigitalTrafficSystem
作为我的开发数据库。表结构是相同的,但开发人员具有非常不同的存储过程。
当恢复运行时,DigitalTrafficSystem
数据库会以dts
数据库中不存在的一堆额外表行结束,所以我假设这些行是由触发器创建的。
对于每个表,我得到的与触发器相关的消息如下所示:
pg_restore: [archiver (db)] could not execute query: ERROR: permission denied: "RI_ConstraintTrigger_c_136691" is a system trigger
Command was: ALTER TABLE usage ENABLE TRIGGER ALL;
我假设(错误地?)触发器已关闭,但只是系统级触发器无法被禁用。
这是我的剧本:
#!/bin/sh
PGUSER=dts
FILE=/tmp/.dts.db.$$
# Dump the schema of the DB as we want this to keep
pg_dump -s DigitalTrafficSystem -f $FILE
dropdb -U _postgres DigitalTrafficSystem
if [ $? -ne 0 ]; then
exit;
fi
createdb -U _postgres -O dts DigitalTrafficSystem
if [ $? -ne 0 ]; then
exit;
fi
# Restore the schema
psql -d DigitalTrafficSystem -f $FILE
# Dump the data of the real production database
pg_dump -Fc -a dts -f $FILE > /dev/null
if [ $? -ne 0 ]; then
exit;
fi
# Restore only the data from the real database to our development one
pg_restore -a -d DigitalTrafficSystem --disable-triggers -S dts $FILE
rm $FILE
答案 0 :(得分:1)
我假设(错误地?)触发器已关闭,但就是这样 系统级触发器无法禁用。
不,因为SQL命令的成功是一个全有或全无的问题。失败的命令可能是以下形式:
ALTER TABLE usage DISABLE TRIGGER ALL;
如果失败,它将完全失败,而不是完成一半的工作,这将禁用用户级触发器并启用RI约束触发器。
pg_restore
doc说:
Presently, the commands emitted for --disable-triggers must be done as superuser. So you should also specify a superuser name with -S or, preferably, run pg_restore as a PostgreSQL superuser.
和
-S username, --superuser=username Specify the superuser user name to use when disabling triggers. This is relevant only if --disable-triggers is used.
但您的dts
不是超级用户。根据脚本的其余部分,似乎_postgres
是超级用户。在这种情况下,为什么不将它传递给-S
?
另一点是,就像@wildplasser在评论中注意到的那样,由于您的脚本创建了一个数据库并立即运行仅数据导入,因此被全新数据库中的触发器所困扰会有点奇怪。我们可以假设它是包含这些对象的template1
数据库,带有这些触发器吗?
但是,请注意,来自template1
的表中的数据也会导入到新创建的数据库中,因此在转储源和最终结果之间找到的任何其他行时也必须考虑它们。目的地数据库。
答案 1 :(得分:0)
需要的是 pg_restore 上的一个选项来仅禁用用户触发器,而不是所有触发器。
pg_restore 问题:ALTER TABLE <table> DISABLE TRIGGER ALL
pg_restore 需要发出这个:ALTER TABLE <table> DISABLE TRIGGER USER