为具有多个多对多关系的视频游戏业务领域设计数据库


16

我对数据库设计比较陌生,因此决定创建自己的假设数据库进行实践。但是,我难以建模和规范化它,因为我认为存在许多多对多(M:N)关系。

一般方案说明

该数据库旨在保留有关在Zelda系列上工作过的各种人员的数据。我想跟踪的控制台(S) ,一个游戏可以玩上,员工是曾在部分游戏的发展,乔布斯员工有(很多员工在不同的工作职位在多个游戏等)

商业规则

  • 多个员工可以从事多个游戏
  • 多个游戏可以在同一控制台上
  • 多个控制台可以是同一游戏的平台。
  • 多个雇员可以具有相同的工作
  • 一个雇员可以有多个工作
  • 一个游戏可以有多个雇员
  • 一个游戏可以有多种类型的乔布斯在它的发展
  • 多个游戏可以附加相同类型的作业
  • 一个控制台可以有多个做这个工作。
  • 一个可以在多个控制台上工作。

属性名称和样本值

  • 员工姓名,可以分成第一最后(例如“约翰”和“李四”)
  • 游戏标题(例如“时间之笛”)
  • 职务(例如“关卡设计”,“导演”,“沉着”,“关卡设计师”,“程序员”,“本地化”等)。
  • 控制台名称(例如“ Game Boy Advance”)

问题

到目前为止,无论我设计什么,似乎到处都存在感兴趣的实体类型之间的数据冗余和M:N关系。但是,我认为数据库设计人员必须始终遇到这种问题,因此必须找到解决方案。


注意:我很容易找到填充表的数据,问题是将其组织到具有标准化表格的数据库中。


1
评论已按要求移至聊天室
保罗·怀特

Answers:


18

是的,对多对多(为简便起见,为M:N)的关联或关系的标识是数据库从业人员在布局概念图时经常面临的情况。所述基数比的关联在性质非常不同的业务环境中出现,并且通过例如SQL-DDL安排在逻辑级别正确表示时,它们不会引入有害的冗余。

这样,数据库建模练习的目标应该是高精度地反映感兴趣的业务上下文的相关特征;因此,如果您正确地识别出存在多个M:N关联,则无论该关联有多少个连接,您都必须在(a)概念模式以及(b)相应的逻辑级别声明中表达它们其他—基数比必须解决。

商业规则

您已经提供了一个经过充分考虑的问题,并且还澄清了您正在使用的数据库纯粹是假设的,这很重要,因为我认为正在考虑的“真实世界”业务场景将更加广泛因此,这意味着更复杂的信息需求。

我决定(1)对您提供的业务规则进行一些修改和扩展,以便(2)产生更具描述性的概念模式(尽管仍然是假设的)。这是我汇总的一些公式:

  • 一个1可以是一个或一个组织
  • 一个是由恰好一个分类PartyType
  • 一个PartyType进行分类零一或一对多的缔约方
  • 一个组织开发零一对多产品
  • 一个产品或者是一个系统或一个游戏
  • 一个产品是由恰好一个分类ProductType
  • 一个系统是由恰好一个编目SystemType中
  • 一个游戏可以通过一个一对多播放系统
  • 一个系统是用来玩一个一对多的游戏
  • 一个游戏是由零一或一对多分类流派
  • 一个类型进行分类零一或一对多的游戏
  • 一个产品源自一个一对多的乔布斯
  • 一个工作是通过零一或一对多履行人民,谁在玩角色合作者
  • 一个是零一个或多个工作协作者

1 缔约方是指在法律范围内指组成单个实体的个人或一组个人时使用的术语,因此该名称适用于代表人员组织


IDEF1X图表

随后,我创建了图1中所示的IDEF1X 2图表(确保单击链接以更高分辨率查看),将上面显示的业务规则(以及一些其他相关的视图)整合到单个图形设备中:

图1-Video Gae Jobs IDEF1X示意图


2 信息建模集成定义IDEF1X)是一种高度推荐的数据建模技术,由美国国家标准技术研究院(NIST)于1993年12月建立为标准。它基于(a)由关系模型的唯一发起人,即EF Codd博士撰写的早期理论材料;(b)由陈PP博士开发的数据的实体关系视图;(c)由Robert G. Brown创建的逻辑数据库设计技术。


如您所见,通过对应的关联实体类型,我仅描绘了三个M:N关联,即:

  • 合作者
  • 系统游戏
  • 游戏类型

除其他方面外,还有两个不同的超型-亚型结构,其中:

  • 个人组织Party的互斥实体子类型,它们的实体超类

  • 产品SystemGame的超类型,而反过来又是互斥的子类型

如果您不熟悉超类型与子类型的关联,则可能会找到帮助,例如,我对题为:

说明性逻辑SQL-DDL布局

接下来,我们必须确保在逻辑层面上:

  • 每种实体类型都由一个单独的基表表示
  • 适用实体类型的每个单个属性都由一个特定的表示
  • 确切的数据类型是固定的每,以确保所有它包含属于特定和良好定义的组,无论是INT,DATETIME,CHAR,等等(当然,使用时,例如,火鸟PostgreSQL的,您可能希望使用功能更强大的DOMAIN)
  • 配置(声明性)多个约束,以确保保留在所有表中的形式的断言符合在概念级别确定的业务规则

因此,我根据先前显示的IDEF1X图声明了以下DDL安排:

CREATE TABLE PartyType ( -- Stands for an independent entity type.
    PartyTypeCode CHAR(1)  NOT NULL, -- To retain 'P' or 'O'.
    Name          CHAR(30) NOT NULL, -- To keep 'Person' or 'Organization'.
    --  
    CONSTRAINT PartyType_PK PRIMARY KEY (PartyTypeCode)
);

CREATE TABLE Party ( -- Represents an entity supertype.
    PartyId         INT       NOT NULL,
    PartyTypeCode   CHAR(1)   NOT NULL, -- To hold the value that indicates the type of the row denoting the complementary subtype occurrence: either 'P' for 'Person' or 'O' for 'Organization'.
    CreatedDateTime TIMESTAMP NOT NULL,  
    --
    CONSTRAINT Party_PK            PRIMARY KEY (PartyId),
    CONSTRAINT PartyToPartyType_FK FOREIGN KEY (PartyTypeCode)
        REFERENCES PartyType (PartyTypeCode)
);

CREATE TABLE Person ( -- Denotes an entity subtype.
    PersonId        INT      NOT NULL, -- To be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    GenderCode      CHAR(3)  NOT NULL,
    BirthDate       DATE     NOT NULL,
    --
    CONSTRAINT Person_PK PRIMARY KEY        (PersonId),
    CONSTRAINT Person_AK UNIQUE             (FirstName, LastName, GenderCode, BirthDate), -- Composite ALTERNATE KEY.
    CONSTRAINT PersonToParty_FK FOREIGN KEY (PersonId)
        REFERENCES Party (PartyId)
);

CREATE TABLE Organization ( -- Stands for an entity subtype.
    OrganizationId  INT      NOT NULL, -- To be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Name            CHAR(30) NOT NULL,
    FoundingDate    DATE     NOT NULL,
    --
    CONSTRAINT Organization_PK        PRIMARY KEY (OrganizationId),
    CONSTRAINT Organization_AK        UNIQUE      (Name), -- Single-column ALTERNATE KEY.
    CONSTRAINT OrganizationToParty_FK FOREIGN KEY (OrganizationId)
        REFERENCES Party (PartyId)
);

CREATE TABLE ProductType ( -- Represents an independent entity type.
    ProductTypeCode CHAR(1)  NOT NULL, -- To enclose the values 'S' and 'G' in the corresponding rows.
    Name            CHAR(30) NOT NULL, -- To comprise the values 'System' and 'Person' in the respective rows.
    --
    CONSTRAINT ProductType_PK PRIMARY KEY (ProductTypeCode)
);

CREATE TABLE Product ( -- Denotes an entity supertype.
    OrganizationId  INT      NOT NULL,
    ProductNumber   INT      NOT NULL,
    ProductTypeCode CHAR(1)  NOT NULL, -- To keep the value that indicates the type of the row denoting the complementary subtype occurrence: either 'S' for 'System' or 'G' for 'Game'.
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Product_PK               PRIMARY KEY (OrganizationId, ProductNumber), -- Composite PRIMARY KEY.
    CONSTRAINT ProductToOrganization_FK FOREIGN KEY (OrganizationId)
        REFERENCES Organization (OrganizationId),
    CONSTRAINT ProductToProductType_FK  FOREIGN KEY (ProductTypeCode)
        REFERENCES ProductType (ProductTypeCode)
);

CREATE TABLE SystemType ( -- Stands for an independent entity type.
    SystemTypeCode CHAR(1)  NOT NULL,
    Name           CHAR(30) NOT NULL,
     --
    CONSTRAINT SystemType_PK PRIMARY KEY (SystemTypeCode)
);

CREATE TABLE MySystem ( -- Represents a dependent entity type.
    OrganizationId   INT      NOT NULL, -- To be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    SystemNumber     INT      NOT NULL,
    SystemTypeCode   CHAR(1)  NOT NULL,
    ParticularColumn CHAR(30) NOT NULL,
    --
    CONSTRAINT System_PK              PRIMARY KEY (OrganizationId, SystemNumber),
    CONSTRAINT SystemToProduct_FK     FOREIGN KEY (OrganizationId, SystemNumber)
        REFERENCES Product (OrganizationId, ProductNumber),
    CONSTRAINT SystemToSystemType_FK  FOREIGN KEY (SystemTypeCode)
        REFERENCES SystemType (SystemTypeCode)
);

CREATE TABLE Game ( -- Denotes an entity subtype.
    OrganizationId INT      NOT NULL, -- To be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    GameNumber     INT      NOT NULL,
    SpecificColumn CHAR(30) NOT NULL,
    --
    CONSTRAINT Game_PK          PRIMARY KEY (OrganizationId, GameNumber),
    CONSTRAINT GameToProduct_FK FOREIGN KEY (OrganizationId, GameNumber)
         REFERENCES Product (OrganizationId, ProductNumber)
);

CREATE TABLE Genre ( -- Stands for an independent entity type.
    GenreNumber INT      NOT NULL,
    Name        CHAR(30) NOT NULL,  
    Description CHAR(90) NOT NULL,
    --
    CONSTRAINT Genre_PK  PRIMARY KEY (GenreNumber),
    CONSTRAINT Genre_AK1 UNIQUE      (Name),
    CONSTRAINT Genre_AK2 UNIQUE      (Description)
);

CREATE TABLE SystemGame ( -- Represents an associative entity type or M:N association.
    SystemOrganizationId INT      NOT NULL,  
    SystemNumber         INT      NOT NULL,  
    GameOrganizationId   INT      NOT NULL,    
    GameNumber           INT      NOT NULL,
    CreatedDateTime      DATETIME NOT NULL,
    -- 
    CONSTRAINT SystemGame_PK         PRIMARY KEY (SystemOrganizationId, SystemNumber, GameOrganizationId, GameNumber), -- Composite PRIMARY KEY.
    CONSTRAINT SystemGameToSystem_FK FOREIGN KEY (SystemOrganizationId, SystemNumber) -- Multi-column FOREIGN KEY.
        REFERENCES MySystem (OrganizationId, SystemNumber),
    CONSTRAINT SystemGameToGame_FK   FOREIGN KEY (SystemOrganizationId, GameNumber) -- Multi-column FOREIGN KEY.
        REFERENCES Game (OrganizationId, GameNumber)  
);

CREATE TABLE GameGenre ( -- Denotes an associative entity type or M:N association.
    GameOrganizationId INT      NOT NULL,    
    GameNumber         INT      NOT NULL,
    GenreNumber        INT      NOT NULL,  
    CreatedDateTime    DATETIME NOT NULL,
    -- 
    CONSTRAINT GameGenre_PK        PRIMARY KEY (GameOrganizationId, GameNumber, GenreNumber), -- Composite PRIMARY KEY.
    CONSTRAINT GameGenreToGame_FK  FOREIGN KEY (GameOrganizationId, GameNumber)
        REFERENCES Game (OrganizationId, GameNumber), -- Multi-column FOREIGN KEY.
    CONSTRAINT GameGenreToGenre_FK FOREIGN KEY (GenreNumber)
        REFERENCES Genre (GenreNumber) 
);

CREATE TABLE Job ( -- Stands for an associative entity type or M:N association.
    OrganizationId  INT      NOT NULL,
    ProductNumber   INT      NOT NULL,
    JobNumber       INT      NOT NULL,
    Title           CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Job_PK          PRIMARY KEY (OrganizationId, ProductNumber, JobNumber), -- Composite PRIMARY KEY.
    CONSTRAINT Job_AK          UNIQUE      (Title), -- Single-column ALTERNATE KEY.
    CONSTRAINT JobToProduct_FK FOREIGN KEY (OrganizationId, ProductNumber) -- Multi-column FOREIGN KEY.
        REFERENCES Product (OrganizationId, ProductNumber)
);

CREATE TABLE Collaborator ( -- Represents an associative entity type or M:N association.
    CollaboratorId   INT      NOT NULL,    
    OrganizationId   INT      NOT NULL,
    ProductNumber    INT      NOT NULL,
    JobNumber        INT      NOT NULL,
    AssignedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Collaborator_PK         PRIMARY KEY (CollaboratorId, OrganizationId, ProductNumber, JobNumber), -- Composite PRIMARY KEY.
    CONSTRAINT CollaboratorToPerson_FK FOREIGN KEY (CollaboratorId)
    REFERENCES Person (PersonId),  
    CONSTRAINT CollaboratorToJob_FK    FOREIGN KEY (OrganizationId, ProductNumber, JobNumber) -- Multi-column FOREIGN KEY.
       REFERENCES Job (OrganizationId, ProductNumber, JobNumber)
);

需要强调的是,在多个表中都有复合 PRIMARY KEY约束的声明,它们表示概念实体类型之间发生的连接层次结构,这种结构对于例如表示SELECT的数据检索非常有益。包含JOIN子句的操作以获取派生表。

是的,(i)每个M:N关联和(ii)每个关联的实体类型都由(iii)逻辑DDL结构中的对应表表示,因此请特别注意PRIMARY和FOREIGN KEY约束(以及代表这些概念性元素的表格的注释(我留为注释),因为它们有助于确保相关行之间的连接满足适用的基数比。

EF Codd博士从关系范式的起源介绍了组合键的用法,正如他在1970年的开创性论文《大型共享数据库的关系模型》中所列举的示例所证明的(确切地说,该模型还介绍了最优雅的方法来处理概念上的M:N关联)。

我放置了 db <> fiddleSQL Fiddle,它们都在Microsoft SQL Server 2014上运行,以便可以“实际”测试结构。

正常化

规范化是一个逻辑级别的过程,基本上可以暗示:

  1. 通过第一个范式消除非原子列,以便通过使用数据的子语言(例如SQL)更轻松地应对数据操作和约束。

  2. 借助连续的范式消除特定表的列之间的不良依赖关系,以避免更新异常

自然,必须考虑所涉及的表和列所具有的含义

我喜欢将规范化视为一种基于科学的测试即设计师在划定稳定的逻辑级别排列以确定其项是否符合每种正常形式后,便将其应用于相关元素。然后,如果需要,设计人员将采取适当的纠正措施。

冗余

在关系模型中,尽管重复包含在列中的值不仅可以接受而且可以预期,但禁止重复行。就此而言,据我所知,在以前公开的逻辑布局中包含的所有表中,都避免了重复行和其他类型的有害冗余,也许您想澄清一下这方面的问题。

无论如何,您当然可以(a)通过正常形式对自己所说的结构进行评估,以定义它是否满足要求,并且(b)必要时进行修改。

相关资源

  • 本系列文章中,我将对一些简单的M:N关联进行一些讨论,这些关联可以使两种不同实体类型的实例相互关联。
  • 另一篇文章中,我提出了一种方法来处理“材料清单”或“零件爆炸”构造的发生,其中我描述了如何连接同一类型实体的不同实例。

三元协会

您还通过注释提出了另一个重要方面(发布在现已删除的答案中):

每当我尝试建立一座桥梁时,这座桥梁中的元素也具有“多对多”的感觉,这给我的印象是不允许或至少不鼓励这样做。

这种情况似乎表明您关注的问题之一与概念性三元关联有关。基本上说,当存在(1)涉及(2)两种其他关系的关系,换句话说是“关系之间的关系”时,也会发生这种关联,这也是一种典型情况,因为关系本身就是一个实体—。

如果妥善管理这些安排,也不会带来有害的冗余。而且,是的,如果在某种特定的用例中您确定这种关系在“现实世界”实体类型之间存在,则您必须(i)建模并(ii)在逻辑级别准确地声明它们。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.