sql - CASCADE 和 RESTRICT 外键要求是否存在冲突?

标签 sql database database-design firebird

我正在开发一个跟踪项目中的文件和依赖项的数据库。简而言之,我有两个主表; PROJECTS 表列出了项目名称和其他属性,FILES 表列出了文件。每个文件条目都作为设置为 CASCADE 的外键指向一个项目,因此,如果我从数据库中删除项目记录,所有文件记录也会消失。到目前为止,一切顺利。

现在我有一个额外的 DEPENDENCIES 表。依赖关系表中的每条记录都是两个文件,指定第一个文件依赖于第二个文件。同样,这些是外键,第一个设置为 CASCADE (因此,如果我删除文件条目,则该记录将被删除),但第二个设置为 RESTRICT (因此,如果任何其他文件依赖于该文件条目,则不允许我删除文件条目在上面)。再说一遍,一切似乎都很好。

不幸的是,我似乎无法再使用单个 SQL 删除语句来删除项目!删除尝试级联删除文件,但如果其中任何一个出现在 DEPENDENCIES 表中,RESTRICT 外键会阻止删除(即使依赖关系表中的记录将被删除,因为另一列是 CASCADE)。我唯一的解决方法是计算删除文件的确切顺序,这样就不会违反任何依赖记录约束,并在尝试删除项目之前一次删除一个文件记录。

是否有任何方法可以设置我的数据库架构,以便从项目表中执行单个 SQL 删除操作就能正确级联其他删除操作?我正在使用 Firebird 2.1,但我不知道这是否有什么区别 - 似乎应该有一种方法可以实现这项工作?

最佳答案

您无法通过级联外键控制删除顺序,但您可以在 PROJECTS 上设计一个触发器来删除 FILES 中属于到此项目,并且也在 DEPENDENCIES 中列为依赖于其他FILES。使其成为 BEFORE DELETE 触发器,因此它应该在级联效果之前执行。

类似这样的事情:

CREATE TRIGGER Del_Child_Files FOR PROJECTS
BEFORE INSERT
AS BEGIN
  FOR SELECT F.FILE_ID FROM FILES F JOIN DEPENDENCIES D 
      ON F.FILE_ID = D.CHILD_ID
    WHERE F.PROJECT_ID = OLD.PROJECT_ID
    INTO :file_id
  DO
    DELETE FROM FILES WHERE FILE_ID = :file_id;
  DONE
END

因此,当您删除项目时,这会删除项目中依赖于其他文件的所有“子”文件,并且会级联删除 DEPENDENCIES 中的行,因此所有剩余文件都是可用的的依赖关系。您对项目的删除现在可以级联删除这些文件。

我还没有测试过这个,我的 Firebird 语法可能很生疏,但也许它会让你开始。

显然,请在您的数据副本上进行测试,而不是实时数据!

关于sql - CASCADE 和 RESTRICT 外键要求是否存在冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/353804/

相关文章:

sql - 如何在 SQL Server 中基于外键进行有效分区?

ruby-on-rails - Rails - 多索引键关联

php - 多种数据类型 - 一张表与多个表

php - 我如何加快此 mysql 查询的速度以在大型 mysql 表(200 万行)中求和一个分数

database - 如何更新 oracle 中一列的所有行,起始值为 500 并在 oracle 中递增

mysql - ER 图 - 与两个不同实体的相同关系

sql - 代表 NCAA 篮球赛的最佳模式

用于创建范围的 SQL

MYSQL查询对某些列的出现次数进行求和

sql - 如果存在语句不起作用