冲突CASCADE和RESTRICT外键要求?

时间:2008-12-09 18:51:01

标签: sql database database-design firebird

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

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

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

有没有办法设置我的数据库模式,以便从项目表中删除一个SQL将正确级联其他删除?我正在使用Firebird 2.1,但我不知道这是否有任何区别 - 似乎应该有办法使这项工作?

2 个答案:

答案 0 :(得分:4)

您无法通过级联外键控制删除顺序,但您可以在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语法可能会生锈,但也许它会让你开始。

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

答案 1 :(得分:0)

系统是否支持延迟约束,其中约束检查可以推迟到提交点?

可能这只是甲骨文的事情。