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

sor*_*h-r 4 database-design foreign-keys directed-acyclic-graphs

我正在编写一个代码来将MySQL数据库备份到二进制文件中.我知道mysqldump但由于某些原因我不能使用琐碎的方法.我目前在做什么:

  1. 读取模式定义
  2. 按外键依赖关系排序表
  3. 选择所有表中的行(每次100行)并将它们写入二进制文件中

依赖关系的定义:当且仅当指向密钥时至少有一个外键时,表T1依赖于表的存在.T2T1T2

为每个表分配一个数值.此值指定表的顺序.对于没有依赖关系的表,此值0对于其他表来说是当前表依赖于它们的表的最大值; 加一.如果-1依赖表的值集合中有一个,则当前表的值仍为undefined(-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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Bra*_*vic 5

循环依赖是相当普遍的.一些例子:

  • 实现"邻接列表"层次结构时,表会引用自身.
  • 在实现1:1 *关系时,两个表互相引用.
  • 两个相互引用的表是1:N关系的可能实现之一(其中"N"侧的行之一是"特殊").
  • 此外,我已经看到多个表形成"环"的情况......

所以是的,拥有循环依赖关系是"好的".


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