PostgreSQL 中的级联删除

Cascading deletes in PostgreSQL

提问人: 提问时间:9/5/2008 最后编辑:Fleury26 更新时间:12/14/2017 访问量:14516

问:

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

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

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

SQL PostgreSQL

评论


答:

0赞 Tony Lenzi 9/5/2008 #1

您可能需要研究将架构与 PostgreSQL 一起使用。在过去的项目中,我这样做是为了允许不同的人群或开发人员拥有自己的数据。然后,您可以使用脚本为这种情况创建数据库的多个副本。

0赞 Please delete this account 9/7/2008 #2

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

0赞 angch 9/11/2008 #3

我认为您不需要像那样处理转储文件。执行流式转储/还原,并对其进行处理。像这样:

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数据库/步骤。

根据您需要这样做的频率、数据库的大小以及敏感数据的百分比,可能还会有更好的方法,但对于一个合理大小的数据库,我想不出一种更简单的方法来做一次或两次。毕竟,您需要一个不同的数据库,因此,除非您已经有一个单独的群集,否则无法避免转储/还原周期,这可能很耗时。

4赞 Grant Johnson 10/1/2008 #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赞 agnul 10/2/2008 #5

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

1赞 user362911 6/10/2010 #6
TRUNCATE table CASCADE;

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

评论

0赞 ShatrdWing 5/4/2017
截断将使表保持存在状态。Drop 将删除表本身。
0赞 Tim Davis 7/24/2010 #7

TRUNCATE 只是从表中删除数据并保留结构