RDBMS数据库中的多对多关系

时间:2010-03-22 12:35:00

标签: sql database-design foreign-keys many-to-many rdbms

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

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

  • 规范化落后于

  • 空列或空的列

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

3 个答案:

答案 0 :(得分:10)

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

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));

然后使用联结表通过外键通过它加入其他表

-- 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 :(得分:4)

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

Student
-------
Id (Primary Key)
FirstName
LastName

Course
------
Id (Primary Key)
Title

StudentCourse
-------------
StudentId (Foreign Key -> Student)
CourseId (Foreign Key -> Course)

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

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)

学生表包含学生信息,课程表存储课程信息......数据透视表只包含相关学生和课程的ID。这不应该导致任何null / empty列或任何东西。

答案 2 :(得分:1)

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