5

I have a database with a few dozen tables interlinked with foreign keys. Under normal circumstances, I want the default ON DELETE RESTRICT behavior for those constraints. But when trying to share a snapshot of the database with a consultant, I needed to remove some sensitive data. I wish that my memory of a DELETE FROM Table CASCADE command hadn't been pure hallucination.

What I ended out doing was dumping the database, writing a script to process the dump by adding ON DELETE CASCADE clauses too all the foreign key constraints, restoring from that, performing my deletes, dumping again, removing the ON DELETE CASCADE, and finally restoring again. That was easier than writing the deletion query I'd have needed to do this in SQL -- removing whole slices of the database isn't a normal operation, so the schema isn't exactly adapted to it.

Does anyone have a better solution for the next time something like this comes up?

4

7 回答 7

4

您不需要转储和恢复。您应该能够删除约束,使用级联重建它,进行删除,再次删除它,然后使用限制重建它。

CREATE TABLE "header"
(
  header_id serial NOT NULL,
  CONSTRAINT header_pkey PRIMARY KEY (header_id)
);

CREATE TABLE detail
(
  header_id integer,
  stuff text,
  CONSTRAINT detail_header_id_fkey FOREIGN KEY (header_id)
      REFERENCES "header" (header_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);
insert into header values(1);
insert into detail values(1,'stuff');
delete from header where header_id=1;
alter table detail drop constraint detail_header_id_fkey;
alter table detail add constraint detail_header_id_fkey FOREIGN KEY (header_id)
      REFERENCES "header" (header_id) on delete cascade;
delete from header where header_id=1;
alter table detail add constraint detail_header_id_fkey FOREIGN KEY (header_id)
      REFERENCES "header" (header_id) on delete restrict;
于 2008-09-30T22:34:48.973 回答
1

您可以将外键约束创建为 DEFERRABLE。然后,您可以在清理数据时暂时禁用它们,并在完成后重新启用它们。看看这个问题

于 2008-10-01T16:17:54.220 回答
1
TRUNCATE table CASCADE;

我是 Postgres 新手,所以我不确定 TRUNCATE 与 DROP 的权衡是什么。

于 2010-06-09T21:44:35.920 回答
0

@Tony:不,模式很有用,事实上,我们使用它们来对数据库中的数据进行分区。但我说的是在让顾问拥有数据库副本之前尝试清理敏感数据。我希望这些数据消失。

于 2008-09-06T16:29:59.587 回答
0

TRUNCATE 只是从表中删除数据并离开结构

于 2010-07-23T17:55:41.997 回答
0

您可能想研究在 PostgreSQL 中使用模式。我在过去的项目中这样做是为了让不同的人群或开发人员拥有自己的数据。然后,您可以使用脚本为此类情况创建数据库的多个副本。

于 2008-09-05T14:08:17.033 回答
0

我认为您不需要像那样处理转储文件。做一个流转储/恢复,并处理它。就像是:

createdb -h scratchserver scratchdb
createdb -h scratchserver sanitizeddb

pg_dump -h liveserver livedb --schema-only | psql -h scratchserver sanitizeddb
pg_dump -h scratchserver sanitizeddb | sed -e "s/RESTRICT/CASCADE/" | psql -h scratchserver scratchdb

pg_dump -h liveserver livedb --data-only | psql -h scratchserver scratchdb
psql -h scrachserver scratchdb -f delete-sensitive.sql

pg_dump -h scratchserver scratchdb --data-only | psql -h scratchserver sanitizeddb
pg_dump -Fc -Z9 -h scratchserver sanitizedb > sanitizeddb.pgdump

您将所有 DELETE sql 存储在 delete-sensitive.sql 中的位置。如果您不介意顾问使用 CASCADE 外键而不是 RESTRICT 外键获取数据库,则可以删除 sanitizeddb 数据库/步骤。

可能还有更好的方法,具体取决于您需要执行此操作的频率、数据库的大小以及敏感数据的百分比,但我想不出更简单的方法来为合理的大小执行一次或两次数据库。毕竟你需要一个不同的数据库,所以除非你已经有一个 slony 集群,否则无法避免转储/恢复周期,这可能很耗时。

于 2008-09-11T15:59:23.703 回答