我必须模拟一种情况,我有一个表 Chequing_Account(其中包含预算、iban 编号和帐户的其他详细信息),该表必须与两个不同的表 Person 和 Corporation 相关,这两个表都可以有 0、1 或多个支票帐户。
换句话说我有两个1对多关系,同一张表支票账户
我想听听尊重规范化要求的这个问题的解决方案。我听到的大多数解决方案是:
1) 找到一个 Person 和 Corporation 都属于的公共实体,并在它和 Chequing_Account 表之间创建一个链接表,这在我的情况下是不可能的,即使我想解决一般问题而不是这个特定实例。
2) 创建两个链接表 PersonToChequingAccount 和 CorporationToChequingAccount,它们将两个实体与支票账户相关联。但是我不希望两个人有同一个支票账户,也不希望一个自然人和一个公司共享一个支票账户!看到这张图片

3) 在 Chequing Account 中创建两个指向 Corporation 和 Natural Person 的外键,但是我会因此强制一个人和一个公司可以拥有多个支票账户,但是我必须手动确保每个 ChequingAccount 行不是两个关系都指向公司和自然人,因为支票账户要么属于公司,要么属于自然人。看到这张图片

这个问题还有其他更清洁的解决方案吗?
Joe*_*own 16
关系数据库并不是为了完美地处理这种情况而构建的。你必须决定什么对你最重要,然后做出权衡。你有几个目标:
问题是其中一些目标相互竞争。
子类型解决方案
您可以选择子类型解决方案,在其中创建包含公司和个人的超类型。这个超类型可能有一个子类型的自然键加上一个分区属性(例如customer_type)的复合键。就规范化而言,这很好,它允许您强制执行参照完整性以及公司和个人相互排斥的约束。问题是这使得数据检索更加困难,因为您总是必须根据customer_type何时将帐户加入帐户持有人来进行分支。这可能意味着UNION在您的查询中使用并拥有大量重复的 SQL。
两个外键解决方案
您可以选择一种解决方案,在您的帐户表中保留两个外键,一个用于公司,一个用于个人。此解决方案还允许您保持参照完整性、规范化和互斥性。它还具有与子类型解决方案相同的数据检索缺点。事实上,这个解决方案就像子类型解决方案一样,只是你会“更快”地解决分支连接逻辑的问题。
尽管如此,由于强制执行互斥约束的方式,许多数据建模者会认为此解决方案不如子类型解决方案。在子类型解决方案中,您使用密钥来强制执行互斥性。在两个外键解决方案中,您使用CHECK约束。我知道有些人对检查约束有不合理的偏见。这些人更喜欢将约束保留在密钥中的解决方案。
“非规范化”分区属性解决方案
还有另一种选择,您可以在支票帐户表上保留单个外键列,并使用另一列来告诉您如何解释外键列(RoKa 的OwnerTypeID列)。通过将分区属性非规范化到子表,这基本上消除了子类型解决方案中的超类型表。(请注意,根据正式定义,这并不是严格的“非规范化”,因为分区属性是主键的一部分。)这个解决方案看起来很简单,因为它避免了额外的表来做或多或少相同的事情,并且将外键列的数量减少到一。此解决方案的问题在于它没有避免检索逻辑的分支,而且它不允许您维护声明性引用完整性。SQL 数据库不
共享主键域解决方案
人们有时处理这个问题的一种方法是使用单一的 ID 池,这样就不会混淆任何给定的 ID,无论它属于一种子类型还是另一种。这在银行场景中可能会很自然地工作,因为您不会向公司和自然人发出相同的银行帐号。这具有避免需要分区属性的优点。您可以使用或不使用超类型表来执行此操作。使用超类型表允许您使用声明性约束来强制唯一性。否则,这将必须在程序上强制执行。此解决方案已规范化,但除非您保留超类型表,否则它不允许您维护声明性引用完整性。它仍然没有避免复杂的检索逻辑。
因此,您可以看到,在遵循所有规则的同时保持简单的数据检索是不可能的。你必须决定你的权衡在哪里。