需要一些建议和反馈来编写许多:MySQL中的许多关系

时间:2012-04-27 05:56:14

标签: mysql sql database database-design relational-database

我在编写许多关系时遇到一些困难:如下图所示:

enter image description here

我想要设置这些表和关系,以便:

  • 父母可以有一个以上的孩子(这里的孩子是 “玩家”),一个孩子可以有一个或多个父母(最多为 二)。
  • “家庭”可以由一个或多个父母组成(最多两个), 还有一个或多个孩子(无限制)。

我不确定如何容纳姓氏不同于“孩子”的父母,反之亦然。我没有被告知这是否会引起关注,但这是我认为值得思考的问题。 Parent和Player类都从一个人超类继承字段(如名字和姓氏,地址,年龄,d.o.b等)。

当我意识到我不确定如何插入一个或多个父母和一个或多个他们是父母(或看护人)的孩子时,我正准备测试家庭表中的一些输入。我以为我在理论上对此进行了整理,但经过测试,我意识到它不起作用,我花了90多分钟做了一些想法的草图,但我真的迷路了。

============================================ ======================================

更新时间:27-04-2012 @ 22:19 PM NZST

我应该直观地展示我正在寻找的结果 - 在查询包含这些表的数据库时。这是视觉表现:

+-------------------+-----------------+---------------------+
| ParentsFirstName  | ParentsLastName | ChildrenInFamily    |
+-------------------+-----------------+---------------------+
| Gregory           | Peck            | Michael             |
| Laura             | Peck            | Michael             |
| Martha            | Petersen        | Matt, Christopher   |
| Chris             | Michaels        | Richard, Shaun      |
| Nadine            | Michaels        | Richard, Shaun      |
| Barry             | Dackers         | Harry               |
| Kevin             | Mitchell        | Daniel              |
| Rebecca           | Mitchell        | Daniel              |
+-------------------+-----------------+---------------------+

“孩子”在一个名为“玩家”的表中,而父母则在一个名为“父母”的表中。这篇文章中的MySQL代码表示有关此特定问题的表(您应该注意到我使用Person类作为超类,父/子表作为子类)。通过使用外键引用了一些其他表(“schoolID”字段来自名为“School”的表,该表具有“schoolName”字段)。

我不确定我是否已根据我想要实现的目标构建了我的表格,但是做了一些研究我发现了一个名为GROUP_CONCAT的函数,它至少让我想到了查询的外观喜欢 - 对于这个特殊的问题。

容纳不具有相同姓氏的父母,以及与父母姓名不同的孩子,是另一个我甚至无法试图解决的重大挑战(我' d想象这也是寄养家庭的情况。因此,对于上述可视化,我假设非单亲父母已经结婚并且拥有相同的姓氏,并且所有孩子都与已婚父母共享相同的姓氏。

============================================ ======================================

以下是我尝试创建试图处理此部分的数据库部分的一些代码(注意:“玩家”是父母的“孩子”):

DROP TABLE IF EXISTS `person` ;
CREATE TABLE `person` (
  `personID` INT(5) NOT NULL AUTO_INCREMENT ,
  `firstName` VARCHAR(50) NOT NULL ,
  `lastName` VARCHAR(50) NOT NULL ,
  `dateOfBirth` DATE NOT NULL ,
  `personType` CHAR(6) NOT NULL, 
  `photo` BLOB NULL DEFAULT NULL ,
  PRIMARY KEY (`personID`))
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `parent` ;
CREATE TABLE `parent` (
  `parentID` INT(5) NOT NULL,
  FOREIGN KEY (`parentID`) REFERENCES `person` (`personID`)
  ON DELETE CASCADE 
  ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `player` ;
CREATE TABLE `player` (
  `playerID` INT(5) NOT NULL, 
  `schoolID` INT(5) NOT NULL,
    FOREIGN KEY (`playerID`) 
    REFERENCES `person` (`personID`)
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
    FOREIGN KEY (`schoolID`)
    REFERENCES `school` (`schoolID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `family` ;
CREATE TABLE `family` (
  `parentID` INT(5) NOT NULL ,
  `playerID` INT(5) NOT NULL ,
  PRIMARY KEY (`parentID`, `playerID`), 
    FOREIGN KEY (`playerID` )
    REFERENCES `player` (`playerID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    FOREIGN KEY (`parentID`)
    REFERENCES `parent` (`parentID`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

如果有人可以通过提供一些指导帮助我解决这个问题,甚至一些带有解释的通用例子,那将是非常好的。我认为这是一个很多:很多关系,我不能完全放弃,因为父母可以有一个或多个孩子,孩子可以有一个或多个父母(在这种情况下,一个家庭不会真正成为没有孩子的家庭)。

非常感谢提前!!!

7 个答案:

答案 0 :(得分:2)

一个孩子不能超过2个父母,他们都有特定的角色(母亲与父亲),并且可能存在父母一方或双方都不知道的情况。

所以这不是一个真正的“多对多”关系,它实际上是“多到零或一两个”,这可以自然地表示为这样(MotherIDFatherID都是NULL-能):

enter image description here

如果您将LastName放在ParentPlayer(或您的案例中的常见超类)中,这也自然会涵盖父母与其子女姓氏不同的情况。

然后,您可以轻松地获得“每个孩子的孩子”(SQL Fiddle)......

SELECT
    ParentID,
    Parent.FirstName ParentFirstName,
    Parent.LastName ParentLastName,
    PlayerID,
    Player.FirstName PlayerFirstName,
    Player.LastName PlayerLastName
FROM
    Parent
    LEFT JOIN Player
        ON Parent.ParentID = Player.MotherID
        OR Parent.ParentID = Player.FatherID
ORDER BY ParentId

...如果您愿意,可以在应用程序代码中转动数据。


上述模型允许Parent的性别与其母亲/父亲角色不匹配。如果你想阻止这种情况,你可以过火并做这样的事情......

enter image description here

...但我宁愿不复杂并坚持使用第一个模型并在应用程序级别强制执行此操作。

答案 1 :(得分:2)

我完全质疑家庭实体的用途。由于离婚和随后的父母再婚,孩子可以成为两个家庭的一员 - 你会如何模仿?一个孩子可能没有四个人有效地“在父母的地方”行事吗?

答案 2 :(得分:1)

所有你需要的是一个有两个领域的联合表:孩子,照顾者。这基本上就是你对“家庭”表的看法 - 我不明白你的“父”表的目的。 “family”中的 BOTH 值将成为“person”的外键(即使'player'比图中的表更通用表。)

然后允许任何孩子拥有任意数量的照顾者。任何照顾者都可以与任意数量的孩子联系。所有可能的乖张和美好家庭安排的组合都得到了满足。

答案 3 :(得分:0)

实现多对多关系的Family表通常在用户输入Parent / Player(s)数据之后创建。用户界面通常被描述为主要表格/子表格组合,其中从主表格输入/选择父母,并且在子表格中输入/显示与父母相关联的一个或多个玩家;通常是某种网格。

答案 4 :(得分:0)

我不确定这是否是"答案"本身,这是我尝试调整我的MySQL代码,以适应 Branko Dimitrijevic 的答案提供给我。这是我为相关表调整的MySQL代码:

DROP TABLE IF EXISTS `person` ;
CREATE TABLE `person` (
  `personID` INT(5) NOT NULL AUTO_INCREMENT ,
  `firstName` VARCHAR(50) NOT NULL ,
  `lastName` VARCHAR(50) NOT NULL ,
  `dateOfBirth` DATE NOT NULL ,
  `personType` CHAR(6) NOT NULL, 
  `photo` BLOB NULL DEFAULT NULL ,
  PRIMARY KEY (`personID`))
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `parent` ;
CREATE TABLE `parent` (
  `parentID` INT(5) NOT NULL,
  PRIMARY KEY (`parentID`), 
  FOREIGN KEY (`parentID`) REFERENCES `person` (`personID`) 
  ON DELETE CASCADE 
  ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

DROP TABLE IF EXISTS `player` ;
CREATE TABLE Player (
    `playerID` INT(5) NOT NULL,
    `motherID` INT(5),
    `fatherID` INT(5),
    `schoolID` INT(5),
    PRIMARY KEY (`playerID`), 
    FOREIGN KEY (`playerID`) REFERENCES `person` (`personID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE,
    FOREIGN KEY (`motherID`) REFERENCES `parent` (`parentID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE,
    FOREIGN KEY (`fatherID`) REFERENCES `parent` (`parentID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
    FOREIGN KEY (`schoolID`) REFERENCES `school` (`schoolID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE)
ENGINE = InnoDB;
SHOW WARNINGS;

这是这些表的逻辑模型的一部分:

enter image description here

如果Branko或其他任何人可以用Branko的答案来验证我的尝试是否合适。另外你会注意到,对于图像我使用MySQL Workbench作为模型。

以下内容超出了此特定问题的范围,但如果有人可以提供帮助,那也很棒:

我被要求不使用反向或正向工程将sql代码转换为模型架构等,但这使我能够验证我在Visio中构建的模型的正确性。但是我不能让Visio模型看起来像Workbench模型 - 这是我试图建模的表的Visio版本:

enter image description here

正如您在Visio版本中看到的那样," fatherID"和#34; motherID"列不表示为外键,这是我想要的(并在Workbench版本中说明)。如果有人可以帮助我让我的Visio模型看起来与Workbench版本相同,那就更好了。

答案 5 :(得分:0)

我不确定为什么一个人会有多个地址 - 但我想他们可以。但是,如果我正在执行多个地址,那么我会将地址推送到另一个表并且有一个person_address连接表。这样,您最终不会为居住在同一地址的每个人重复地址数据。

您的父表需要两个字段 - 一个用于父级,另一个用于播放器(正如我之前所说的 BOTH 我认为如果它们都指向人员,它会更好用)。你为什么在paren和玩家之间有两条关系?

person | parent关系不会是1..1 - 1..1,因为这意味着每个人都是父母,你的玩家可能不是。

撇开 - 但你真的看起来似乎注重了母亲和父亲。两者中任何一个都可能没有。您不需要单独的关系来规定性别 - 应该是PERSON中的数据,或者根本不相关的数据。

答案 6 :(得分:0)

好吧这太痛苦了。你过得很复杂了。我没有visio所以尝试和应对:

  • PERSON(person_id,first_name,last_name)PK:person_id
  • FAMILY(父母,球员)PK :(父母,球员)FK:FAMILY.parent - > PERSON.person_id,FK:player-> PERSON.person_id

多数民众赞成 - 简单。

您需要的只是一张桌子,可以将两个不同的人聚在一起。为了找到孩子的所有看护人,你只需加入人与人并为孩子过滤。

地址:

  • PERSON_ADDRESS(person_id,address_id)PK:(person_id,address_id)FK:person_id-> person.person_id,FK:address_id-> address.address_id
  • ADDRESS(address_id,st-num,street,city,phone)PK:address_id其中st-num可能是23B等字样的字母数字

实际上 - 我对你把电话放在地址里感觉不舒服。不会扩展到地址中的多个电话号码。但地址是一种分心。你的问题似乎是关于将球员与父母联系起来。

学校应该是自己的桌子。要么将school_id放到人身上,要么如果你讨厌null,那么就有一个加入表person_school,它只有孩子们的记录