数据库设计 – 为具有多个多对多关系的视频游戏业务域设计数据库
我对数据库设计比较陌生,我决定建立自己的假设数据库进行实践.但是,我在建模和规范化时遇到了麻烦,因为我认为存在许多多对多(M:N)关系.
一般情景描述 该数据库旨在保留有关使用塞尔达系列的各种人员的数据.我想跟踪可以玩游戏的控制台,参与游戏开发的员工,员工的工作(许多员工在多个游戏中从事不同的工作)等. 商业规则 >多名员工可以参与多个游戏. 属性名称和样本值 >员工姓名,可以拆分为第一个和最后一个(例如“John”和“Doe”) 问题 到目前为止,似乎无论我设计什么,数据冗余和M:N关系到处都是感兴趣的实体类型.但是我觉得数据库设计者必须一直遇到这种问题,所以必须有一个解决方案. 注意:我能够找到填充表格的数据,问题是将其组织成一个数据库,其中包含规范化形式的表格. 解决方法是的,识别多对多(简称为M:N)关联或关系是数据库从业者在布局概念模式时非常常见的情况.所述基数的关联在非常不同的商业环境中通常是重要的,并且当通过例如SQL-DDL安排在逻辑级别适当地表示时,它们不会引入有害的冗余.通过这种方式,数据库建模练习的目标应该是高精度地反映所关注的商业环境的重要特征;因此,如果你正确地识别出有许多M:N关联,那么你必须在(a)概念模式中以及(b)相应的逻辑级声明中表达它们,无论它有多少个连接 – 或任何必须解决其他类型的基数问题. 商业规则 您提供了一个语境良好的问题,并且还澄清了您正在处理的数据库纯粹是低调的,这是一个重要的观点,因为我认为像正在考虑的业务领域的“真实世界”案例将是更广泛的. 我决定(1)对你提供的业务规则进行一些修改和扩展,以便(2)产生一个更具描述性的概念模式 – 尽管还是假设的 – .以下是我放在一起的一些配方: > Party1是个人或组织 1缔约方在提及组成单一实体的个人或一组个人时,在法律背景中使用的术语,因此该面额适合代表人和组织. IDEF1X图 随后,我创建了Figure 1中显示的IDEF1X2图表(确保单击链接以更高的分辨率查看它),在单个图形设备中合并上面提供的业务规则(以及其他一些看起来相关的规则): 2信息建模的集成定义(IDEF1X)是一种非常值得推荐的数据建模技术,由美国国家标准与技术研究院(NIST)于1993年12月作为标准建立.它完全基于(a)由关系模型的发起者撰写的早期理论材料,即E. F. Codd博士; (b)Dr. P. P. Chen entity-relationship开发的数据视图;以及(c)由Robert G. Brown创建的逻辑数据库设计技术. 如您所见,我通过相应的关联实体类型仅描绘了三个M:N关联,即: >合作者, 在其他方面,有两种不同的超类型 – 子类型结构,其中: >人与组织是党的互斥实体子类型,其实体超类型;和 如果您不熟悉超类型 – 子类型关联,您可能会找到帮助,例如,我对问题的答案 >“Modeling a scenario in which each Music Artist is either a Group or a Solo Performer”, 说明性的逻辑SQL-DDL布局 接下来,我们必须确保在逻辑层面: >每个实体类型由单个基表表示; 所以我根据之前显示的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,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,-- Composite PRIMARY KEY. CONSTRAINT SystemGameToSystem_FK FOREIGN KEY (SystemOrganizationId,SystemNumber) -- Multi-column FOREIGN KEY. REFERENCES MySystem (OrganizationId,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,-- 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,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,-- Composite PRIMARY KEY. CONSTRAINT CollaboratorToPerson_FK FOREIGN KEY (CollaboratorId) REFERENCES Person (PersonId),CONSTRAINT CollaboratorToJob_FK FOREIGN KEY (OrganizationId,JobNumber) -- Multi-column FOREIGN KEY. REFERENCES Job (OrganizationId,JobNumber) ); 强调跨多个表的复合PRIMARY KEY约束的声明是恰当的,这些表代表在概念实体类型之间发生的连接的层次结构,这种安排在例如表达SELECT操作时对于数据检索是非常有益的.包括JOIN以获取派生表. 是,(i)每个M:N关联和(ii)每个关联实体类型由(iii)逻辑DDL结构中的对应表表示,因此要特别注意PRIMARY和FOREIGN KEY约束(以及表示这些概念元素的表格留下的评论,因为它们有助于确保相关行之间的连接符合适用的基数. 复合键的使用是从关系范式的起源于Dr. E. F. Codd引入的,正如他在1970年的开创性论文A Relational Model for Large Shared Data Banks中所包含的例子中所证明的那样(正是,它也提供了处理概念M:N关联的最优雅的方法). . 我提出了a db<>fiddle和a SQL Fiddle,它们都在Microsoft SQL Server 2014上运行,因此可以对结构进行测试. 正常化 规范化是一个逻辑层次的过程,基本上说, >通过第一范式消除非原子列,以便通过使用的数据子语言(例如,SQL)更容易处理数据操作和收缩;和 当然,必须考虑所讨论的表格和列所带有的含义. 我喜欢把规范化看作是建立在科学基础上的测试,一旦设计师设计了稳定的逻辑层次安排以确定其项目是否符合所有正常形式,设计师就会将其应用于相关元素.然后,如果需要,设计者采取适当的纠正措施. 冗余 在关系模型中,虽然列中包含的值的重复不仅可以接受,而且是预期的,但禁止重复行.在这种程度上,据我所知,在之前暴露的逻辑布局中包含的所有表中都会阻止重复行和其他类型的有害冗余,或许您想澄清您在这方面的关注. 无论如何,您当然可以(a)通过正常形式评估您自己的结构,以确定它是否符合要求,以及(b)在必要时进行修改. 相关资源 >在this series of posts中,我提出了一些关于直接M:N关联的讨论,该关联可以使两种不同实体类型的实例相互关联. 三元协会 您通过评论提出了另一个重要方面(发布在现已删除的答案中):
这种情况似乎表明您的一个问题与概念三元关联有关.基本上,当存在(1)涉及(2)其他两种关系的关系时,这种关联就出现了,换句话说,“关系之间的关系” – 一种典型的情况 – . 在适当管理的情况下,这些安排也不会带来有害的冗余.并且,是的,如果存在某个用例,您确定此类关系在“真实世界”实体类型中出现,则必须(i)建模并且(ii)在逻辑级别上准确地声明它们. > Here is a question and answer我们分析了一个关于调查的话语领域,其中包括一个三元关联的例子. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |