PostgreSQL中的级联删除

时间:2008-09-05 12:04:51

标签: sql postgresql

我有一个数据库,其中有几十个表与外键相互关联。在正常情况下,我希望这些约束的默认ON DELETE RESTRICT行为。但在尝试与顾问共享数据库快照时,我需要删除一些敏感数据。我希望我对DELETE FROM Table CASCADE命令的记忆不是纯粹的幻觉。

我最终做的是转储数据库,编写脚本来处理转储,同时添加ON DELETE CASCADE子句所有外键约束,从中恢复,执行删除,再次转储,删除{{ 1}},最后再次恢复。这比编写我在SQL中需要执行此操作所需的删除查询更容易 - 删除数据库的整个切片不是正常操作,因此架构并不完全适应它。

有没有人有更好的解决方案,以便下次出现这样的事情?

7 个答案:

答案 0 :(得分:4)

您无需转储和恢复。您应该能够删除约束,使用级联重建它,执行删除操作,再次删除它,并使用restrict重建它。

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;

答案 1 :(得分:1)

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

答案 2 :(得分:1)

TRUNCATE table CASCADE;

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

答案 3 :(得分:0)

您可能希望在PostgreSQL中使用schemas。我在过去的项目中已经完成了这项工作,以允许不同的人员或开发人员拥有自己的数据。然后,您可以使用脚本为这种情况创建数据库的多个副本。

答案 4 :(得分:0)

@Tony:不,架构可能很有用,实际上,我们使用它们来划分数据库中的数据。但我正在谈论在让顾问拥有数据库副本之前尝试擦除敏感数据。我希望这些数据消失。

答案 5 :(得分: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 sqls存储在delete-sensitive.sql中。如果您不介意顾问使用CASCADE外键而不是RESTRICT外键获取数据库,则可以删除sanitizeddb数据库/步骤。

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

答案 6 :(得分:0)