【问题标题】:Conflicting CASCADE and RESTRICT foreign key requirements?冲突的 CASCADE 和 RESTRICT 外键要求?
【发布时间】:2008-12-09 18:51:01
【问题描述】:

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

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

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

有什么方法可以设置我的数据库架构,以便从项目表中删除单个 SQL 将正确地级联其他删除?我正在使用 Firebird 2.1,但我不知道这是否有什么不同 - 似乎应该有办法让这项工作发挥作用?

【问题讨论】:

    标签: sql database database-design firebird


    【解决方案1】:

    您无法通过级联外键控制删除顺序,但您可以在PROJECTS 上设计一个触发器来删除FILES 中属于该项目且也列在@987654323 中的行@ 依赖于其他 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 语法可能会生锈,但也许它会让你开始。

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

    【讨论】:

    • 我绝对喜欢在触发器而不是应用程序代码中执行此操作的想法。我会试一试,看起来这将是我的答案:)
    【解决方案2】:

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

    也许这只是 Oracle 的事情。

    【讨论】:

    • Firebird 不支持延迟约束。
    猜你喜欢
    • 2014-01-04
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 2017-12-31
    • 1970-01-01
    相关资源
    最近更新 更多