Как реализовать связь многие ко многим
Перейти к содержимому

Как реализовать связь многие ко многим

  • автор:

Пример связи «многие-ко-многим»

Здравствуйте! Не могу понять связь «многие ко многим». Что она значит? Приведите, пожалуйста, пример, когда эту связь нужно устанавливать. Лучше даже пример из жизни приведите, пожалуйста, когда такая связь осуществляется.

Отслеживать
задан 11 янв 2012 в 12:45
elenavictory elenavictory
320 3 3 золотых знака 7 7 серебряных знаков 23 23 бронзовых знака

3 ответа 3

Сортировка: Сброс на вариант по умолчанию

«Один-ко-многим» — тип связи таблиц, когда одной записи главной таблицы можно сопоставить несколько записей подчинённой таблицы. Это наиболее частый вид связи между таблицами. Ну, например, если создавать телефонный справочник, то необходимо учесть, что у одного человека может быть несколько телефонов (2 мобильных, 1 домашний и 1 служебный). Или ещё пример: студент (записи о студентах хранятся в главной таблице) обучается в ВУЗе — он изучает несколько предметов (записи о предметах хранятся в подчинённой таблице), по которым сдаёт экзамены и зачёты.

А связь «многие-ко-многим» возникает в тех случаях, когда одной записи одной таблицы может соответствовать несколько записей другой таблицы и наоборот: когда одной записи второй таблицы может соответствовать несколько записей первой таблицы. От такого типа связи следует избавляться и приводить к виду «один-ко-многим». Пример такого вида связи: имеем 2 таблицы «Товары» и «Клиенты», каждый клиент может приобрести несколько товаров, в свою очередь каждый товар (по наименованию) может быть приобретён (или заказан) несколькими клиентами. Ещё пример (по ВУЗ): пусть есть 2 таблицы «Преподаватель» и «Студент», каждый преподаватель может обучать нескольких студентов, в то же время каждый студент может обучаться у нескольких преподавателей.

Отслеживать
ответ дан 11 янв 2012 в 12:54
DelphiM0ZG DelphiM0ZG
3,045 15 15 серебряных знаков 18 18 бронзовых знаков
А, например, в Access как устанавливается подобная связь в схеме данных?
10 ноя 2016 в 4:03
Почему «От такого типа связи следует избавляться»? Связь как связь.
1 дек 2016 в 8:40

Примеры, приведённые для связи «многие-ко-многим» хоть и верные по сути, ошибочны с точки зрения проектирования бд:) например, в примере про студентов — каждый студент состоит в группе, а преподаватель преподаёт предмет. У группы есть предметы, обратной связи никакой:) ну то есть по логике связи «многие ко многим» тут неоткуда взяться.

Построение связи «многие ко многим» (визуальные инструменты для баз данных)

Отношения «многие ко многим» позволяют связать каждую строку одной таблицы с несколькими строками другой таблицы и наоборот. Например, отношение «многие ко многим» можно создать для таблиц authors и titles , чтобы связать каждого автора с его книгами и сопоставить каждой книге ее автора. Если создать связь «один ко многим» в любой таблице, получится, что каждая книга сможет иметь только одного автора или каждый автор — только одну книгу.

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

Для создания связи «многие ко многим» между таблицами

  1. Добавьте таблицы, которые должны обладать связью «многие ко многим» в диаграмму базы данных.
  2. Создайте третью таблицу, щелкнув диаграмму правой кнопкой мыши и выбрав Создать таблицу . Эта таблица станет связующей.
  3. В диалоговом окне Выбор имени измените имя, назначенное системой. Например, связующую таблицу для таблиц titles и authors можно назвать titleauthors .
  4. Скопируйте первичные ключевые столбцы обеих таблиц в связующую таблицу. В эту таблицу можно добавить другие столбцы, как в любую другую таблицу.
  5. Создайте первичный ключ в связующей таблице так, чтобы он содержал все первичные ключевые столбцы исходных таблиц. Дополнительные сведения см. в разделе Как Создайте первичные ключи.
  6. Определите отношение «один ко многим» между каждой из первоначальных таблиц и связующей таблицей. Связующая таблица должна находиться на стороне «многих» обоих отношений. Дополнительные сведения см. в разделе Как Создайте связи между таблицами.

Примечание Создание связующей таблицы в диаграмме базы данных не подразумевает ее заполнение данными из связанных таблиц. Дополнительные сведения о вставке данных в эту таблицу см. в разделе Создание запросов вставки результатов (визуальные инструменты для баз данных).

Как реализовать связь многие ко многим

Отношение многие-ко-многим предполагает, что сущность одного типа одновременно может иметь связи с множеством сущностей другого типа и наоборот. Например, один студент может посещать несколько университетских курсов. Соответственно один университетский курс может посещаться множеством студентов. То есть есть в данном сслучае имеем связь многие ко многим.

Физически на уровне базы данных обычно для создания подобной связи создается промежуточная таблица, через которую связываются две основные таблицы. В Sequelize поэтому для связи двух сущностей отношением многие-ко-многим нам надо задать промежуточную модель. Так, возьмем пример с курсами и студентами:

const Sequelize = require("sequelize"); // определяем объект Sequelize const sequelize = new Sequelize( < dialect: "sqlite", storage: "metanit.db", define: < timestamps: false >>); const Student = sequelize.define("student", < id: < type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false >, name: < type: Sequelize.STRING, allowNull: false >>); const Course = sequelize.define("course", < id: < type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false >, name: < type: Sequelize.STRING, allowNull: false >>); // промежуточная сущность, которая связывает курс и студента const Enrolment = sequelize.define("enrolment", < id: < type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false >, grade: < // оценка студента по данному курсу type: Sequelize.INTEGER, allowNull: false >>); Student.belongsToMany(Course, ); Course.belongsToMany(Student, ); sequelize.sync().then(()=>< console.log("Tables have been created"); >).catch(err=>console.log(err));

Здесь в качестве промежуточной сущности выступает модель Enrolment — по сути данные успеваемости определенного студента по определенному курсу. В этой модели можно определить различные свойства. Так, в данному случае определено свойство «grade», которое призвано хранить оценку студена по данному курсу. Аналогично в этой модели мы могли бы определить какие-нибудь атрибуты, которые бы связывали студента с курсом, например, дату поступления на данный курс, дату окончания и т.д.

Непосредственно для создания связи многие-ко-многим применяется метод belongsToMany() . Первый параметр метода — сущность, с которой надо установить связь. Второй параметр — объект конфигурации связи, который с помощью параметра through обязательно должен задавать промежуточную сущность, через которую будут связаны обе основные сущности.

В итоге при выполнении данного кода в базе данных SQLite будут созданы три таблицы с помощью следующих SQL-команд:

CREATE TABLE IF NOT EXISTS `students` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255) NOT NULL); CREATE TABLE IF NOT EXISTS `courses` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255) NOT NULL); CREATE TABLE IF NOT EXISTS `enrolments` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `grade` INTEGER NOT NULL, `studentId` INTEGER REFERENCES `students` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, `courseId` INTEGER REFERENCES `courses` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE (`studentId`, `courseId`) );

Добавление связанных данных

При установке связи многие ко многим модели могут использовать метод addИМЯ_МОДЕЛИ() для добавления объектов (например, student.addCourse() и course.addStudent() ). Например, пусть у нас будет создано несколько объектов — студентов и курсов:

Course.create(< name: "JavaScript">); Course.create(< name: "TypeScript">); Course.create(< name: "Node.js">); Student.create(< name: "Tom">); Student.create(< name: "Bob">); Student.create(< name: "Alice">);

Добавим студенту с именем Tom курс по JavaScript:

// получаем пользователя с именем Tom Student.findOne(>) .then(student=>< if(!student) return; // добавим Тому курс по JavaScript Course.findOne(>) .then(course=>< if(!course) return; student.addCourse(course, >); >); >);

Первым параметром в student.addCourse() передается добавляемый курс. Вторым параметром устанавливается значение для столбца grade в таблице enrolments. В итоге данный метод будет выполнять sql-команду:

INSERT INTO `enrolments` (`id`,`grade`,`studentId`,`courseId`) VALUES (NULL,1,1,3);

Получение связанных данных

Для получения связанных данных у каждой из моделей, участвующих в связи, мы можем использовать метод getИМЯ_МОДЕЛИs() . Например, получим все курсы студента по имени Tom:

Student.findOne(>) .then(student=>< if(!student) return; student.getCourses().then(courses=> < for(course of courses)< console.log(course.name); >>); >);

Однако в реальности в данном случае мы получаем не просто курс из таблицы courses, а сводные данные на основании таблицы enrolments — выполняемая sql-команда в данном случае будет выглядеть следующим образом:

SELECT `course`.`id`, `course`.`name`, `enrolment`.`id` AS `enrolment.id`, `enrolment`.`grade` AS `enrolment.grade`, `enrolment`.`studentId` AS `enrolment.studentId`, `enrolment`.`courseId` AS `enrolment.courseId` FROM `courses` AS `course` INNER JOIN `enrolments` AS `enrolment` ON `course`.`id` = `enrolment`.`courseId` AND `enrolment`.`studentId` = 1;

То есть в данном случае мы сможем получить название и id курса, а также id и значение grade объекта Enrolment:

Student.findOne(>) .then(student=>< if(!student) return; student.getCourses().then(courses=> < for(course of courses)< console.log("course:", course.name, "grade:", course.enrolment.grade); >>); >);

Удаление связанных данных

Для удаления связанных данных необходимо получить объект из промежуточной таблицы и удалить его. Например, удалим у студента по имени Tom курс JavaScript:

Student.findOne(>) .then(student=>< if(!student) return; student.getCourses().then(courses=> < for(course of courses)< if(course.name==="JavaScript") course.enrolment.destroy(); >>); >);

Создание связей типа «многие-ко-многим»

Браузер не поддерживает видео. Установите Microsoft Silverlight, Adobe Flash Player или Internet Explorer 9.

Связи типа «многие-ко-многим» используются между таблицами чаще всего. С их помощью можно узнавать важные сведения, например, с какими клиентами связывались ваши менеджеры по продажам и какие продукты входили в заказы.

Связь «многие-ко-многим» предполагает возможность связи одного или нескольких элементов из одной таблицы с одним или несколькими элементами из другой таблицы. Примеры:

  • В таблице «Заказы» указаны заказы, сделанные разными клиентами из таблицы «Клиенты». Каждый клиент мог сделать несколько заказов.
  • В таблице «Продукты» указаны продаваемые товары, каждый из которых может фигурировать в нескольких заказах из таблицы «Заказы».
  • Каждый продукт может входить в один заказ как в одном, так и в нескольких экземплярах.

Например, в заказ Арины Ивановой № 1012 могут входить продукты № 12 и 15, а также пять продуктов № 30.

Создание связи «многие-ко-многим»

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

В рассмотренном ранее примере создавалась таблица «Сведения о заказах» с записями, в которых для каждого товара в нужном порядке указывались номер заказа из таблицы «Заказы» и код продукта из таблицы «Продукты». Первичный ключ для этой таблицы создавался путем объединения ключей из двух других таблиц.

Ниже рассмотрим пример, когда в заказ Арины Ивановой № 1012 входят продукты № 12, 15 и 30. Это значит, что записи в таблице «Сведения о заказах» выглядят следующим образом:

Арина заказала по одному продукту № 12 и 15, а также пять продуктов № 30. Создать другие строки с номером заказа 1012 и кодом продукта 30 нельзя, потому что поля «Номер заказа» и «Код продукта» вместе составляют первичный ключ, а первичные ключи должны быть уникальными. Вместо этого можно добавить в таблицу «Сведения о заказах» поле «Количество».

Создание промежуточной таблицы

Сохранение

  1. Выберите Создание >Таблица.
  2. Выберите Сохранить

Создание полей в промежуточной таблице

В качестве первого столбца таблицы Access автоматически добавляет поле идентификатора. Измените имя этого поля на идентификатор вашей первой таблицы в связи «многие-ко-многим». Например, если первая таблица называется «Заказы», поле «Код» в ней переименовано в «Номер заказа», и его первичный ключ — число, измените имя поля «Код» в новой таблице на «Номер заказа», а в качестве типа данных выберите Числовой.

  1. В режиме таблицы выберите заголовок столбца Код и введите новое имя поля.
  2. Выберите переименованное поле.
  3. На вкладке Поля таблицы в разделе Тип данных выберите тип данных, соответствующий полю в исходной таблице, например Число или Короткий текст.
  4. Щелкните надпись Щелкните для добавления и выберите тип данных, соответствующий первичному ключу во второй таблице. В заголовке столбца введите имя поля первичного ключа из второй таблицы, например «Код продукта».
  5. Если вам требуется отслеживать другую информацию об этих записях, например количество товаров, создайте дополнительные поля.

Объединение полей для создания первичного ключа

Теперь, когда у вас есть поля с идентификаторами двух таблиц, между которыми вы хотите создать связь, в промежуточной таблице следует создать первичный ключ на основе этих идентификаторов.

Снимок экрана: первичный ключ в таблице

  1. Откройте промежуточную таблицу в режиме конструктора.
  2. Выберите обе строки с идентификаторами. (Если вы следовали предыдущим указаниям, это будут две первые строки.)
  3. Выберите Конструктор таблиц >первичный ключ.
    Значки клавиш отображаются рядом с обоими полями идентификаторов.

Соединение трех таблиц для создания связи «многие-ко-многим»

Чтобы завершить создание связи «многие-ко-многим», создайте связь «один-ко-многим» между полем первичного ключа в каждой таблице и соответствующим полем в промежуточной таблице. Инструкции см. в статье Начало работы со связями между таблицами.

После этого связи должны выглядеть следующим образом:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *