提问人: 提问时间:9/5/2008 最后编辑:Fleury26 更新时间:12/14/2017 访问量:14516
PostgreSQL 中的级联删除
Cascading deletes in PostgreSQL
问:
我有一个数据库,其中包含几十个与外键相互链接的表。在正常情况下,我想要这些约束的默认行为。但是,当尝试与顾问共享数据库的快照时,我需要删除一些敏感数据。我希望我对命令的记忆不是纯粹的幻觉。ON DELETE RESTRICT
DELETE FROM Table CASCADE
我最终做的是转储数据库,编写一个脚本来处理转储,通过添加子句来处理转储所有外键约束,从中恢复,执行我的删除,再次转储,删除 ,最后再次恢复。这比在SQL中编写删除查询更容易 - 删除数据库的整个切片不是正常操作,因此架构并不完全适应它。ON DELETE CASCADE
ON DELETE CASCADE
下次出现这样的事情时,有没有人有更好的解决方案?
答:
您可能需要研究将架构与 PostgreSQL 一起使用。在过去的项目中,我这样做是为了允许不同的人群或开发人员拥有自己的数据。然后,您可以使用脚本为这种情况创建数据库的多个副本。
@Tony:不,模式可能很有用,事实上,我们使用它们来对数据库中的数据进行分区。但我说的是尝试在让顾问拥有数据库副本之前清理敏感数据。我希望这些数据消失。
我认为您不需要像那样处理转储文件。执行流式转储/还原,并对其进行处理。像这样:
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数据库/步骤。
根据您需要这样做的频率、数据库的大小以及敏感数据的百分比,可能还会有更好的方法,但对于一个合理大小的数据库,我想不出一种更简单的方法来做一次或两次。毕竟,您需要一个不同的数据库,因此,除非您已经有一个单独的群集,否则无法避免转储/还原周期,这可能很耗时。
您不需要转储和还原。您应该能够删除约束,使用级联重建它,执行删除操作,再次删除它,然后使用 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;
您可以将外键约束创建为 DEFERRABLE。然后,您可以在清理数据时暂时禁用它们,并在完成后重新启用它们。看看这个问题。
TRUNCATE table CASCADE;
我是 Postgres 新手,所以我不确定 TRUNCATE 与 DROP 的权衡是什么。
评论
TRUNCATE 只是从表中删除数据并保留结构
评论