换句话说,我与同一个表Chequing帐户有两个1对多的关系
我想听听这个问题的解决方案,它们遵守规范化要求.
我听过的大多数解决方案是:
1)找到Person和Corporation都属于的公共实体,并在此和Chequing_Account表之间创建一个链接表,这在我的情况下是不可能的,即使它是我想解决一般问题而不是这个特定实例.
2)创建两个链接表PersontochequingAccount和CorporationtochequingAccount,它们将两个实体与Chequing Accounts相关联.但是我不希望两个人拥有相同的支票账户,而且我不想让一个自然人和公司分享一个支票账户!看到这个图像
3)在Chequing账户中创建两个指向公司和自然人的外键,但是我会强制执行一个人和一个公司可以拥有许多支票账户但是我必须手动确保每个ChequingAccount行不是两个关系指向公司和自然人,因为一个checquing帐户是公司或自然人.看到这个图像
这个问题还有其他更清洁的解决方案吗?
解决方法
>保持第三范式
>保持参照完整性
>维护每个帐户属于公司或自然人的约束.
>保留简单直接检索数据的能力
问题是其中一些目标相互竞争.
子打字解决方案
您可以选择一种子类型解决方案,您可以在其中创建包含公司和人员的超类型.这种超类型可能具有子类型的自然键的复合键加上分区属性(例如customer_type).就规范化而言,这很好,它允许您强制执行参照完整性以及公司和人员相互排斥的约束.问题是,这使得数据检索更加困难,因为当您将帐户加入帐户持有者时,您始终必须根据customer_type进行分支.这可能意味着使用UNION并在查询中包含大量重复sql.
两个外键解决方案
您可以选择一种解决方案,其中您在帐户表中保留两个外键,一个到公司,一个到一个人.此解决方案还允许您保持参照完整性,规范化和互斥性.它还具有与子类型解决方案相同的数据检索缺陷.实际上,这个解决方案就像子打字解决方案一样,只是你遇到了“更快”分支加入逻辑的问题.
然而,由于实施互斥约束的方式,许多数据建模者会认为这种解决方案不如子打字解决方案.在子输入解决方案中,您可以使用键来强制实现互斥性.在两个外键解决方案中,您使用CHECK约束.我知道有些人对检查限制有不合理的偏见.这些人更喜欢将约束保留在密钥中的解决方案.
“非规范化”分区属性解决方案
还有另一种选择,您可以在chequing帐户表上保留一个外键列,并使用另一列来告诉您如何解释外键列(RoKa的OwnerTypeID列).这基本上通过将分区属性非规范化为子表来消除子类型解决方案中的超类型表. (请注意,根据形式定义,这不是严格的“非规范化”,因为分区属性是主键的一部分.)这个解决方案看起来非常简单,因为它避免了有一个额外的表来做或多或少相同的事情而且它将外键列的数量减少到一个.这个解决方案的问题在于它不会避免检索逻辑的分支,而且它不允许您维护声明性引用完整性. sql数据库无法管理多个父表之一的单个外键列.
共享主键域解决方案
人们有时处理这个问题的一种方法是使用单个ID池,这样就不会混淆任何给定的ID,无论它是属于一个子类型还是另一个子类型.这可能会在银行业务场景中很自然地发挥作用,因为您不会向公司和自然人发放相同的银行帐号.这具有避免需要分区属性的优点.您可以使用或不使用超类型表来执行此操作.使用超类型表允许您使用声明性约束来强制唯一性.否则,必须在程序上强制执行.此解决方案已规范化,但除非保留超类型表,否则不允许维护声明性参照完整性.它仍然无法避免复杂的检索逻辑.
因此,您可以看到,实际上不可能拥有遵循所有规则的干净设计,同时保持数据检索的简单性.你必须决定你的权衡取舍.