数据库设计:单个表中的一对一关系?

时间:2017-08-04 22:27:22

标签: mysql sql database database-design

对于学校科目,我必须制作一个具有不同类型关系的小型应用程序:一对一,一对多,多对多。

例如,如果来自同一个表'用户'的2个用户ID之间的关系状态(与某个关系结婚)仍然是一对一的关系?

例如:

表1:'用户'

user_id(PK)|用户名|密码| date_registered

表2:'关系'

user_one_id(FK)| user_two_id(FK)|状态

这是一对一数据库的正确示例,还是本身必须是两个表之间的连接,外部表连接它们?

2 个答案:

答案 0 :(得分:2)

简短的回答并不是真的。

当您在两个表的主键之间建立关系时,就会得到一对一的关系。

接受你的想法:说我们有很多用户,但是我们在这样的表中跟踪他们的登录信息:

CREATE TABLE users (
    user_id int NOT NULL PRIMARY KEY,
    username varchar,
    password varchar);

还有另一张表:

CREATE TABLE user_personal(
    user_id int NOT NULL PRIMARY KEY,
    age int,
    firstname varchar,
    lastname varchar)

一旦您创建了这两个表,就很容易看到每个表中都有一列具有相同的数据类型(user_id),用作该表的主键。 / p>

如果使用user_id作为关键字在两个表之间建立关系,则您已建立一对一的关系,因为user_id只能在任一表中出现一次。

这可能看起来有点奇怪,因为您可能会问为什么要将数据分开。为什么要区分您在一个表中包含哪些数据字段而不是另一个表中的数据字段?一个简单的解决方案是数据隔离。假设我们修改了第二个表来显示:

CREATE TABLE user_personal(
    user_id int NOT NULL PRIMARY KEY,
    age int,
    firstname varchar(255),
    lastname varchar(255),
    home_address varchar(255),
    social_security_number int)

我们可能希望向某些人提供某些数据,但不能访问其他人。如果您有自己的用户关系表,那么向某些人展示人们彼此之间的家庭/友谊关系可能会很好,但您不想放弃他们的社会安全号码和家庭住址。您可能将数据分离出来的另一个重要原因是您的表中是否包含大量数据(请考虑数百列),并且只有部分数据会在任何特定时间更新。如果您有数百万条记录需要更新,但只有某些列一起更新而其他列保持相当静态,您可以将该表分成两个具有一对一关系的表,以防止数据库性能陷入困境更新流程。

答案 1 :(得分:1)

如果“连接它们的外部表”是指第三个表,那么不,这是没有必要的。

你的关系表可以使用一些工作。您不希望有两个带有用户ID的字段。那会让你头疼。我建议像这样设置这些表:

USER

user_id (pk)
username
password        --Potential security problems, but for academic purposes, sure.
date_registered
family_unit_id


RELATIONSHIP

family_unit_id (fk)
user_id (fk)
spouse_type --(e.g. husband, wife, etc.)

现在,您可以通过以下方式获得多对多的关系:

SELECT r.family_unit_id, r.user_id, u.username
FROM RELATION r LEFT JOIN USER u ON r.user_id = u.user_id

您的一对一关系将成为表之间相同记录所特有的关系。在您描述的情况下,与user_id(妻子)相关的user_id(丈夫)不是一对一的关系。根据您所提供的内容,您可以通过加入数据的子集来建立一对一的关系,例如此示例。

SELECT r1.family_unit_id, r1.username as HusbandName, r2.username as WifeName
FROM (SELECT * FROM RELATION WHERE spouse_type = 'Husband') r1
LEFT JOIN (SELECT * FROM RELATION WHERE spouse_type = 'Wife') r2
     ON r2.family_unit_id = r1.family_unit_id

上述查询基本上获得两个表,其中包含family_unit_ids的唯一主键和与丈夫或妻子相关联的用户ID。然后,你加入他们。因为我们假设在这个例子中,已婚家庭单位中的配偶永远不会超过两个,这将是一对一的关系。

如果您想获得一对多关系,您可以从USER表中选择所有内容,然后加入RELATIONSHIP表以显示合作伙伴在关系中的位置:

SELECT u.username, r.user_id
FROM USER u LEFT JOIN RELATIONSHIP r ON r.family_unit_id = u.family_unit_id

当然这将是一个微不足道的结果,因为你会有记录说约翰与约翰和玛丽有关系。但它说明了这一点。通常,通过在此混合中添加更多表,您将获得更多有用的一对多关系结果。