我认为你没有得到你需要的答案的原因是你提出问题的方式。与其问“我如何发现实体之间正确的关系类型”,不如想想“我的功能需求如何决定要实现什么关系”。数据库设计不驱动功能;正是功能需求推动了您需要实施的关系。
在设计数据库结构时,您需要识别所有实体。实体是您要存储的所有事实:诸如书名、发票、国家、犬种等的列表。然后,要确定您的关系,您必须考虑要向数据库询问的问题类型。有时需要进行一些前瞻性思考……仅仅因为没有人现在问这个问题并不意味着它可能永远不会被问到。所以你不能问宇宙“这些事实清单之间的关系是什么?”因为没有确定的答案。你定义了宇宙……我只想知道这些问题的答案;因此我需要使用这种类型的关系。
让我们来看看两个常见实体之间的示例关系:客户表和商店位置表。如果不首先定义您需要了解的有关它们的信息,就没有“正确”的方式来关联这些实体。假设您为一家零售商工作,并且您想为客户指定一个默认商店名称,以便他们可以在网站上看到他们当地商店有库存的产品。这只需要商店和客户之间的一对多关系。以这种方式设计关系可确保一个商店可以有许多客户作为他们的默认客户,而每个客户只能有一个默认商店。要实现这种关系,只需将DefaultStore 字段作为链接到Store 表主键的外键添加到Customer 表中即可。
上述相同的两个实体可能对不同上下文中的关系定义有不同的要求。假设我需要能够让客户有机会选择最喜欢的商店列表,以便他们可以一次查询所有这些商店的库存信息。这需要多对多关系,因为您希望一个客户能够与许多商店相关联,并且每个商店也可以与许多客户相关联。实现多对多关系需要更多的开销,因为您必须创建一个单独的表来定义关系链接,但是您可以获得这个额外的功能。您可以将您的关系表称为CustomerStoreFavorites 之类的名称,并将其主键作为来自每个实体的组合主键:(CustomerID, StoreID)。您还可以向关系中添加属性,例如可能是 LastOrderDate 字段,以指定客户从特定商店订购商品的最后日期。
从技术上讲,您可以为相同的两个实体定义两种类型的关系。举个例子:也许您需要让客户选择默认商店,但您还需要能够记录客户从特定商店订购商品的最后日期。您可以使用Store 表的外键在Customer 表上实现DefaultStore 字段并创建一个关系表来跟踪客户已订购的所有商店。
如果您遇到一些奇怪的情况,即每个客户都有自己的商店,那么您甚至不需要为您的实体创建两个表,因为您可以将客户和商店的所有属性都放在一个表中。
简而言之,确定要实施哪种类型的关系的方式是问自己需要向数据库询问哪些问题。您设计它的方式将限制您可以收集的关系数据以及您可以询问的查询。如果我设计了从商店到客户的一对多关系,我将无法询问有关每个客户订购的所有商店的问题,除非我可以通过其他关系获得该信息。例如,我可以创建一个名为“purchases”的实体,它与客户和商店具有一对多的关系。如果将每次购买定义为与一位客户和一家商店相关,那么现在我可以查询“该客户从哪些商店订购过?”事实上,通过这种结构,我能够捕获和报告关于客户在任何商店的所有购买的更丰富的信息来源。因此,您还需要考虑数据库中所有其他关系的上下文,以决定在两个特定实体之间实现哪种关系。
没有神奇的公式,所以只需要练习、经验和一点点创造力。 ER 图是一种让您的设计脱离头脑并写在纸上的好方法,这样您就可以分析您的设计并确保您可以回答正确类型的问题。还有很多书籍和资源可以学习数据库架构。我从中学到很多东西的一本好书是 Abraham Silberschatz 和 Henry Korth 的“数据库系统概念”。