我很少遇到这样的情况:多个实体类型的单个表似乎比每个实体类型一个表好.这是一个对我有意义的例子,但在学术上它似乎是错误的.
问题:我可以这样做并且仍然具有"声音"架构吗?
示例如下
假设有两种实体类型,一个公司和一个人.公司通常由一个人拥有,但有时另一家公司拥有公司.
坚持这一想法并加入其中,让我们说每个公司都有一个附属于它的注册代理人,负责公司的合法创建.进一步说明,注册代理人可以是个人或公司.
如果您认为公司[子女]的所有者[父母]可以是个人或公司,您可能会开始看到保持第三种正常形式并避免冗余的挑战.
与我的例子相反,如果只有人可以拥有公司,则所有权链接表非常传统,具有列:OwnershipID(有点不必要),CorporateID,PersonID.
相反,您需要以下内容:OwnershipID,CorporationID,OwnerID,OwnerEntityType(corp或person).不要误会我的意思,你可以做到这一点,但至少可以说它不会很有趣.
继续我给出的示例,您需要为每个公司分配代理.通常,代理人是所有者(一个人)之一.在这种情况下,您确实想要链接回该人的一条记录.您不希望将此人的记录作为所有者,然后再将其作为代理记录(在代理表中).这将是多余的.
与该"问题"类似,注册代理人也可以是公司,例如律师事务所,注册会计师或商业申请公司,以列举一些典型的例子.就像代理人一样,代理公司真的不应该作为代理人实体获得自己的记录.相反,它需要链接回公司表中的公司存在.[除了我最终说没有公司实体表]
就像链接表将每个公司与其所有类型,个人或公司的所有者相匹配一样,您可以拥有一个代理链接表:AgentRepresentationID,CorporationID,AgentID,AgentType ......但同样,它会很难看( IMO)当你必须把相关的代理 - 一些来自Person表,一些来自公司表.
这就是为什么我说,在这种情况下,你可以看到中性实体类型如何有利.它会是这样的:
表:EntityAll
键列:EntityID,EntityType(或EntityTypeID,如果您坚持,链接以获取描述),EntityName(有关于名称和不同类型的问题...关于此帖子的主题)
链接表:CorporationOwnership
Key Columns:OwnershipID(再次,我的评论,这是一种不必要的),ChildEntityID(被拥有的实体;为了清楚起见,命名为"Child",我不会将其命名为)ParentEntityID(父实体)
链接表:AgentRepresentation
键列:AgentRepresentationID(...我不会说出来),CorporationEntityID(正在表示的公司实体),AgentEntityID(来自Entity表,等于此处代理的记录)
虽然您对我的架构可能没问题,但您应该对链接表中的列命名感到困扰.这让我很烦.通常,这些表中的第二个和第三个列名称与每个实体的相应表中的JOIN列完全匹配(哈哈,但是每个实体都没有相应的表,因此您不能使链接表列名匹配源列名称,因为它们是相同的列).从技术上讲,这无关紧要,但它会破坏你的命名约定,这些约定很重要,但还不足以做到这一点.
如果我还没有把它推回家,那么你将如何把它拉到一起.您可以自己加入EntityAll表以获得所需内容.
列出所有军团及其所有者(在T-SQL中):
SELECT Corp.EntityName as CorpName, Owner.EntityName as OwnerName
FROM EntityAll as Corp
JOIN CorporationOwnership as Link on (Corp.EntityID = Link.ChildEntityID)
JOIN EntityAll as Owner on (Link.ParentEntityID = Owner.EntityID)
Run Code Online (Sandbox Code Playgroud)
因此,您可以执行相同的操作来返回代理,而不是所有者.
我意识到这不是我们如何训练构建表格,但我非常强烈地认为我的解决方案可以消除冗余数据并使代码,管理和读取变得更加容易.
PS我最近提供了这个例子作为SO的旧问题的答案.作为一个老问题,没有对话.我需要实现这个例子,我很好奇这个架构的后果.
以下是上一个问题/答案: 良好的数据库表设计:一个表混合不同的实体或每个实体的单独表