如果一个表通过两个多对多关系引用另一个表,则禁止数据不一致

kak*_*mba 6 foreign-key database-design constraint consistency

我有以下数据库设计(通过=>外键约束描述):

公司[编号]
CompanyRealm[id, company_id=>Company.id] many2many

项目[id, company_id=>Company.id]
ProjectRealm[id, project_id=>Project.id, company_realm_id=>CompanyRealm.id] many2many

问题是提供的数据库设计允许不一致的数据。例如:

公司1 (id= 1 )
公司 2(id= 2 )
CompanyRealm(id=11, company_id= 1 )
项目(id=33, company_id= 2 )
ProjectRealm(id=44, project_id=33, company_realm_id=11)

Company可以有很多RealmsProject属于Company可以涉及任意数量的公司的Realms

ProjectRealm 指的是两个不同的公司:

  • Company1(通过 CompanyRealm);和
  • Company2(通过项目)。

我的数据库设计有问题吗?
如果是 - 违反了哪些处方?
如果否 - 如何防止错误的数据插入(通过约束?触发异常?)

ype*_*eᵀᴹ 7

你是对的,设计允许不一致,正是你注意到的。AProjectRealm可能既指代Project一家公司又指代CompanyRealm另一家公司。

这并不少见,当关系中有三角形或“菱形”形状时就会出现:

Realm          Company
   \           /     \
    \         /       \
     \       /         \
    CompanyRealm     Project
             \         /
              \       /  
               \     /    
             ProjectRealm
Run Code Online (Sandbox Code Playgroud)

通用解决方案,如果您想通过 DRI(声明性引用完整性)强制执行此操作,即。通过平时UNIQUEFOREIGN KEYCHECK约束-而不是触发虽然-是使用复合键的ProjectRealm REFERENCES CompanyRealm并为ProjectRealm REFERENCES Project外键。

您需要将 替换为company_realm_id2 列 ( company_id, realm_id) 并UNIQUE在两个引用表中的每一个上添加复合约束(或修改它们的PRIMARY KEY):

Company [id]

Realm [id]

CompanyRealm [id, realm_id=>Realm.id, company_id=>Company.id,
              UNIQUE(company_id, realm_id)]

Project [id, company_id=>Company.id,
         UNIQUE(company_id, id)]

ProjectRealm [id, project_id, company_id, realm_id,
              (company_id, project_id) => Project (company_id, id),
              (company_id, realm_id) => CompanyRealm (company_id, realm_id)]
Run Code Online (Sandbox Code Playgroud)

另请参阅其他几个问题,其中出现相同(或非常相似)的问题。菱形图案一目了然:

  • 不,如果我没记错的话,它们是 3NF,也可能是 5NF。似乎 `company_id` 在 `ProjectRealm` 中是多余的,是的。在某种程度上它是但因为它是`UNIQUE` 键的一部分(`(project_id, company_id, realm_id)` 是唯一的,我认为)它不违反任何NF。我想我已经广泛讨论了另一个问题,让我找到链接。顺便说一句,如果是我的设计,我会删除“CompanyRealm (id)”和“ProjectRealm (id)”,除非它们是针对特定的性能问题,以及您计划在其中实施的 DBMS。 (3认同)