Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL中的级联删除_Sql_Postgresql - Fatal编程技术网

PostgreSQL中的级联删除

PostgreSQL中的级联删除,sql,postgresql,Sql,Postgresql,我有一个数据库,其中有几十个表与外键相连。在正常情况下,我希望这些约束的默认行为是DELETE RESTRICT。但当我试图与顾问共享数据库快照时,我需要删除一些敏感数据。我希望我对deleteofromtable CASCADE命令的记忆不是纯粹的幻觉 我最后做的是转储数据库,编写一个脚本来处理转储,方法是在DELETE CASCADE子句中添加所有外键约束,从中恢复,执行删除,再次转储,删除DELETE CASCADE上的,最后再次恢复。这比在SQL中编写删除查询要容易得多——删除整个数据库

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

我最后做的是转储数据库,编写一个脚本来处理转储,方法是在DELETE CASCADE子句中添加所有外键约束,从中恢复,执行删除,再次转储,删除DELETE CASCADE上的
,最后再次恢复。这比在SQL中编写删除查询要容易得多——删除整个数据库片段不是一个正常的操作,因此模式不能完全适应它


下次出现类似的问题时,有谁有更好的解决方案吗?

您可能需要考虑与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
将所有删除sql存储在DELETE-sensitive.sql中。如果您不介意顾问使用级联外键而不是限制外键获得db,则可以删除SanitizeDB数据库/步骤


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

您不需要转储和恢复。您应该能够删除约束,使用cascade重建约束,执行删除操作,再次删除约束,然后使用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;

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


我是Postgres的新手,所以我不确定TRUNCATE和DROP之间的权衡。

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

TRUNCATE将保留表。Drop将删除表本身。
TRUNCATE table CASCADE;