在关系数据库中是否可以使用循环外键依赖项?

时间:2013-02-09 20:36:43

标签: database-design foreign-keys directed-acyclic-graphs

我正在编写代码来将MySQL数据库备份到二进制文件中。我知道mysqldump,但由于某些原因,我无法使用琐碎的方法。我现在在做什么:

  1. 读取架构定义
  2. 按外键依赖项排序表
  3. 选择所有表中的行(每次100行)并将其写入二进制文件
  4. 依赖关系的定义:表T1取决于表T2的存在,当且仅当T1中有一个外键指向T2&#时39;关键。

    为每个表分配一个数值。此值指定表的顺序。对于没有依赖关系的表,对于其他表,该值为0,它是当前表依赖于它们的表的最大值;加一。如果依赖表的值集合中存在-1,则当前表的值仍未定义(-1)。最初所有表的值都是-1,这意味着未指定。

    这是C ++代码:

    // tablesQueue: Queue of all tables
    // orderedQueue: Resulting order
    
    while(! tablesQueue.isEmpty())
    {
        bool satisfied = true;
        foreach(TableNode* parent, tablesQueue.head()->referencedTables)
        {
            if(parent->degreeOfFreedom == -1)
            {
                satisfied = false;
                break;
            }
            else
               // handle error blah blah ... 
        }
        if(satisfied)
        {
            int max =0;
            foreach(TableNode* parent, tablesQueue.head()->referencedTables)
            max = (max < parent->degreeOfFreedom+1) ? 
                      parent->degreeOfFreedom+1 : max;
            tablesQueue.head()->degreeOfFreedom = max;
            orderedQueue.enqueue(tablesQueue.dequeue());
        }
        else
        {
            tablesQueue.enqueue(tablesQueue.dequeue());
        }
    }
    

    如果表的依赖图中存在循环,则此算法不会终止。

    通常可以为表设置这样的设计吗?例如,两个表彼此具有外键。令人惊讶的是,我发现Oracle for MySQL(sakila)提供的示例数据库有很多这样的周期。我假设可以通过添加第三个表来删除所有周期[?]

1 个答案:

答案 0 :(得分:5)

循环依赖很常见。一些例子:

  • 在实施"adjacency list"层次结构时,表会引用自身。
  • 在实施1:1 * 关系时,两个表互相引用。
  • 两个相互引用的表是1:N关系的可能实现之一(“N”侧的一行是“特殊”)。
  • 此外,我见过多个表形成“响铃”的情况......

所以是的,拥有循环依赖是“没关系”。


* 严格地说, true 1:1需要延迟约束才能解决鸡蛋问题(MySQL不支持),否则你只能有1:0..1或0..1:0..1。但在所有这些情况下,您有两个相互引用的表。