关于sql:RDBMS数据库中的多对多关系

Many-to-many relations in RDBMS databases

在像 mySQL 这样的 RDBMS 数据库中处理多对多关系的最佳方法是什么?

已尝试使用数据透视表来跟踪关系,但它会导致以下任一情况:

  • 规范化被抛在后面

  • 为空或 null

    的列

您采取了哪些方法来支持多对多关系?


在专门用于该关系的表(有时称为联结表)中跟踪多对多关系。此表将关系建模为两个指向相反方向的一对多关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE customer (
    customer_id VARCHAR NOT NULL,
    name VARCHAR NOT NULL,
    PRIMARY KEY (customer_id));

CREATE TABLE publication (
    issn VARCHAR NOT NULL,
    name VARCHAR NOT NULL,
    PRIMARY KEY (issn));

-- Many-to-many relationship for subscriptions.
CREATE TABLE subscription (
    customer_id VARCHAR NOT NULL,
        FOREIGN KEY customer_id REFERENCES customer (customer_id),
    issn VARCHAR NOT NULL,
        FOREIGN KEY issn REFERENCES publication (issn),
    BEGIN TIMESTAMP NOT NULL,
    PRIMARY KEY (customer_id, issn));

然后,您可以使用联结表通过外键连接其他表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- Which customers subscribe to publications named 'Your Garden Gnome'?
SELECT customer.*
FROM customer
    JOIN subscription
        ON subscription.customer_id = customer.customer_id
    JOIN publication
        ON subscription.issn = publication.issn
WHERE
    publication.name = 'Your Garden Gnome';

-- Which publications do customers named 'Fred Nurk' subscribe to?
SELECT publication.*
FROM publication
    JOIN subscription
        ON subscription.issn = publication.issn
    JOIN customer
        ON subscription.customer_id = customer.customer_id
WHERE
    customer.name = 'Fred Nurk';


我会使用数据透视表,但我看不出您的问题来自哪里。使用一个简单的学生/班级示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Student
-------
Id (PRIMARY KEY)
FirstName
LastName

Course
------
Id (PRIMARY KEY)
Title

StudentCourse
-------------
StudentId (FOREIGN KEY -> Student)
CourseId (FOREIGN KEY -> Course)

或者,正如其他人在回答您的学生/教师/课程问题时提到的那样(这将有一个额外的表格来存储课程中的人员类型):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PersonType
----------
Id (PRIMARY KEY)
TYPE

Person
------
Id (PRIMARY KEY)
FirstName
LastName
TYPE (FOREIGN KEY -> PersonType)

Course
------
Id (PRIMARY KEY)
Title

PersonCourse
------------
PersonId (FOREIGN KEY -> Person)
CourseId (FOREIGN KEY -> Course)

Student 表包含学生信息,Course 表存储课程信息……而数据透视表仅包含相关学生和课程的 ID。这不应该导致任何空/空列或任何东西。


除了贾斯汀的回答:如果您巧妙地使用外键约束,您可以控制数据更新或删除时发生的情况。这样,您就可以确保您不会得到非规范化的数据。