Отношения «многие ко многим» в базах данных РСУБД - PullRequest
5 голосов
/ 22 марта 2010

Каков наилучший способ обработки отношений «многие ко многим» в базе данных СУБД, такой как mySQL?

Попытка использовать сводную таблицу для отслеживания отношений, но это приводит к одному из следующих действий:

  • Нормализация остается позади

  • Пустые или нулевые столбцы

Какой подход вы выбрали для поддержки отношений «многие ко многим»?

Ответы [ 3 ]

11 голосов
/ 22 марта 2010

Отслеживайте отношение «многие ко многим» в таблице специально для этого отношения (иногда называемой соединительной таблицей ). В этой таблице моделируются отношения как два отношения «один ко многим», указывающие в противоположных направлениях.

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';
4 голосов
/ 22 марта 2010

Я бы использовал сводную таблицу, но не понимаю, откуда возникли ваши проблемы. Используя простой пример ученика / класса:

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)

Таблица Студента содержит информацию об ученике, таблица Курса хранит информацию о курсе ... а сводная таблица просто содержит идентификаторы соответствующих студентов и курсов. Это не должно приводить к пустым / пустым столбцам или чему-либо еще.

1 голос
/ 22 марта 2010

В дополнение к ответу Джастина: если вы умело используете ограничения внешнего ключа, вы можете контролировать, что происходит, когда данные обновляются или удаляются.Таким образом, вы можете быть уверены, что данные не нормализуются.

...