Как реализовать отношения один-к-одному, один-ко-многим и многие-ко-многим при разработке таблиц?


281

Кто-нибудь может объяснить, как реализовать отношения один-к-одному, один-ко-многим и многие-ко-многим при разработке таблиц с некоторыми примерами?


Реализация имеет тенденцию варьироваться в зависимости от целевой СУБД, так на какого поставщика вы ориентируетесь?
billinkc

1
это не домашнее задание ... !! Я готовлюсь к собеседованию. Вот и подумал, чтобы спросить здесь ... Я попытался поискать в Google, но не нашел ни одной хорошей статьи, где бы я объяснил все это в одном ... !!
арсенал

Я нацеливаюсь на базу данных оракула .. !!
арсенал

Вы можете также прочитать этот пост .... stevencalise.wordpress.com/2010/09/01/… Я бы обратил пристальное внимание на пункты 2 и 3.
Рассказывает

3
@ tsells Иногда вам задают вопросы, которые не относятся к тому, что есть в вашем резюме или непосредственно к требованиям к работе. Мне дали список людей, которые будут брать у меня интервью в одной компании, а один был экспертом по БД. В моем резюме не было SQL, но я разбирался с несколькими простыми SQL-запросами. Это помогло, и я получил работу. Позже я узнал, что менеджер по найму был обеспокоен тем, как кандидаты реагируют под давлением. Они признают свои пределы или фальсифицируют свой путь? Если они признают свои пределы, они все равно пытаются или сдаются слишком рано?
Даг Катбертсон

Ответы:


479

Один-к-одному: используйте внешний ключ для ссылочной таблицы:

student: student_id, first_name, last_name, address_id
address: address_id, address, city, zipcode, student_id # you can have a
                                                        # "link back" if you need

Вы также должны наложить уникальное ограничение на столбец внешнего ключа ( addess.student_id), чтобы несколько строк в дочерней таблице ( address) не связывались с одной и той же строкой в ​​ссылочной таблице ( student).

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

teachers: teacher_id, first_name, last_name # the "one" side
classes:  class_id, class_name, teacher_id  # the "many" side

Многие ко многим : используйте соединительную таблицу ( пример ):

student: student_id, first_name, last_name
classes: class_id, name, teacher_id
student_classes: class_id, student_id     # the junction table

Примеры запросов:

 -- Getting all students for a class:

    SELECT s.student_id, last_name
      FROM student_classes sc 
INNER JOIN students s ON s.student_id = sc.student_id
     WHERE sc.class_id = X

 -- Getting all classes for a student: 

    SELECT c.class_id, name
      FROM student_classes sc 
INNER JOIN classes c ON c.class_id = sc.class_id
     WHERE sc.student_id = Y


1
Что является хорошим примером того, когда «обратная связь» полезна в отношениях «один к одному»? Спасибо за четкий и краткий ответ.
dev_feed

1
@dev_feed С точки зрения дизайна базы данных, я не считаю, что обратная ссылка будет полезной, но использование приведенного выше примера обратной ссылки может упростить поиск studentзаданного an address.
хеджирует

@NullUserException - нам нужно 3 таблицы для отношения «многие ко многим». Это не может быть сделано двумя таблицами отношения «многие ко многим».

1
@Cody Каждая student_classesстрока должна иметь только одно отношение «один к одному». Если studentAесть в classAи classB, то должно быть две строки student_classes, одна для которых отношения.
NullUserException

11
В отношении один к одному поле соединения должно быть уникальным в обеих таблицах. Вероятно, PK в одной таблице гарантирует уникальность, но для другой таблицы может потребоваться уникальный индекс.
HLGEM

70

Вот некоторые реальные примеры типов отношений:

Один на один (1: 1)

Отношение является взаимно-однозначным, если и только если одна запись из таблицы A связана максимум с одной записью в таблице B.

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

Например:

CREATE TABLE Gov(
    GID number(6) PRIMARY KEY, 
    Name varchar2(25), 
    Address varchar2(30), 
    TermBegin date,
    TermEnd date
); 

CREATE TABLE State(
    SID number(3) PRIMARY KEY,
    StateName varchar2(15),
    Population number(10),
    SGID Number(4) REFERENCES Gov(GID), 
    CONSTRAINT GOV_SDID UNIQUE (SGID)
);

INSERT INTO gov(GID, Name, Address, TermBegin) 
values(110, 'Bob', '123 Any St', '1-Jan-2009');

INSERT INTO STATE values(111, 'Virginia', 2000000, 110);

Один ко многим (1: М)

Отношение является одним-ко-многим, если и только если одна запись из таблицы A связана с одной или несколькими записями в таблице B. Однако одна запись в таблице B не может быть связана с несколькими записями в таблице A.

Чтобы установить отношение «один ко многим», первичный ключ таблицы A (таблица «one») должен быть вторичным ключом таблицы B (таблица «many»).

Например:

CREATE TABLE Vendor(
    VendorNumber number(4) PRIMARY KEY,
    Name varchar2(20),
    Address varchar2(20),
    City varchar2(15),
    Street varchar2(2),
    ZipCode varchar2(10),
    Contact varchar2(16),
    PhoneNumber varchar2(12),
    Status varchar2(8),
    StampDate date
);

CREATE TABLE Inventory(
    Item varchar2(6) PRIMARY KEY,
    Description varchar2(30),
    CurrentQuantity number(4) NOT NULL,
    VendorNumber number(2) REFERENCES Vendor(VendorNumber),
    ReorderQuantity number(3) NOT NULL
);

Многие ко многим (М: М)

Отношение много-ко-многим тогда и только тогда, когда одна запись из таблицы A связана с одной или несколькими записями в таблице B и наоборот.

Чтобы установить отношение «многие ко многим», создайте третью таблицу с именем «ClassStudentRelation», которая будет иметь первичные ключи как таблицы A, так и таблицы B.

CREATE TABLE Class(
    ClassID varchar2(10) PRIMARY KEY, 
    Title varchar2(30),
    Instructor varchar2(30), 
    Day varchar2(15), 
    Time varchar2(10)
);

CREATE TABLE Student(
    StudentID varchar2(15) PRIMARY KEY, 
    Name varchar2(35),
    Major varchar2(35), 
    ClassYear varchar2(10), 
    Status varchar2(10)
);  

CREATE TABLE ClassStudentRelation(
    StudentID varchar2(15) NOT NULL,
    ClassID varchar2(14) NOT NULL,
    FOREIGN KEY (StudentID) REFERENCES Student(StudentID), 
    FOREIGN KEY (ClassID) REFERENCES Class(ClassID),
    UNIQUE (StudentID, ClassID)
);

1-й пример: номер GID (6) и номер SGID (4), почему? Разве SGID также не должен быть (6)? А на втором примере номер (4) и номер (2) ...
обеликсз

@obeliksz может быть нулем?
Му корова

Почему вы используете UNIQUE (StudentID, ClassID) в конце M: N?
strix25

1
@ strix25 Чтобы избежать повторения при создании одной и той же строки ClassStudentRelation несколько раз, потому что, если вы не убедитесь, что оба внешних ключа StudentID и ClassID уникальны, что останавливает создание новой строки с одинаковыми StudentID и ClassID? поскольку они не уникальны в коде выше. Таким образом, вы либо реализуете его, как в коде выше, либо добавляете первичный ключ, который включает в себя и StudentID, и ClassID, чтобы избежать повторения создания одной и той же строки в ClassStudentRelation.
Фуад Букредин

1
@valik Данные в базах данных работают, ссылаясь на существующие данные, а не создавая один и тот же фрагмент данных несколько раз, зачем вам это делать? конечно, не нужно, иначе это не эффективно. Имея это в виду, давайте вернемся к вашему примеру (у Джеймса есть биология, а у биологии есть джеймс). Конечно, вы можете, НО без создания другого фрагмента данных, который уже существует в базе данных. Все, что вам нужно сделать, это просто ссылаться на уже существующий, когда вы хотите создать какие-либо отношения. Я надеюсь, что это помогает :)
Фуад Букредин

8

Это очень распространенный вопрос, поэтому я решил превратить этот ответ в статью .

Один ко многим

Отношение «один ко многим» выглядит следующим образом:

Один ко многим

В системе реляционной базы данных отношение таблицы «один ко многим» связывает две таблицы на основе Foreign Keyстолбца в дочернем элементе, который ссылается на Primary Keyстроку родительской таблицы.

На приведенной выше диаграмме таблицы post_idстолбец post_commentтаблицы имеет Foreign Keyотношение к столбцу postидентификатора таблицы Primary Key:

ALTER TABLE
    post_comment
ADD CONSTRAINT
    fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post

Один к одному

Табличное отношение один к одному выглядит следующим образом:

Один к одному

В системе реляционной базы данных отношение таблицы «один к одному» связывает две таблицы на основе Primary Keyстолбца в дочернем элементе, который также Foreign Keyссылается на Primary Keyстроку родительской таблицы.

Следовательно, мы можем сказать, что дочерняя таблица делится Primary Keyс родительской таблицей.

На приведенной выше диаграмме таблицы idстолбец post_detailsтаблицы также имеет Foreign Keyотношение к столбцу postтаблицы id Primary Key:

ALTER TABLE
    post_details
ADD CONSTRAINT
    fk_post_details_id
FOREIGN KEY (id) REFERENCES post

Многие-ко-многим

Отношение «многие ко многим» выглядит следующим образом:

Многие-ко-многим

В системе реляционной базы данных отношение таблицы «многие ко многим» связывает две родительские таблицы через дочернюю таблицу, которая содержит два Foreign Keyстолбца, ссылающихся на Primary Keyстолбцы двух родительских таблиц.

На приведенной выше диаграмме таблицы post_idстолбец post_tagтаблицы также имеет Foreign Keyотношение к столбцу postидентификатора таблицы Primary Key:

ALTER TABLE
    post_tag
ADD CONSTRAINT
    fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post

И tag_idстолбец в post_tagтаблице имеет Foreign Keyотношение к столбцу tagидентификатора таблицы Primary Key:

ALTER TABLE
    post_tag
ADD CONSTRAINT
    fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag

3

Отношение один к одному (1-1): это отношение между первичным и внешним ключом (первичный ключ относится только к одной записи внешнего ключа). это отношения один на один.

Отношение «один ко многим» (1-M): это также отношение между отношениями первичного и внешнего ключей, но здесь первичный ключ относится к нескольким записям (т. Е. В таблице A содержится информация о книге, а в таблице B - несколько издателей одной книги).

Многие ко многим (ММ): « Многие ко многим» включает в себя два аспекта, полностью объясненных ниже как пример.

-- This table will hold our phone calls.
CREATE TABLE dbo.PhoneCalls
(
   ID INT IDENTITY(1, 1) NOT NULL,
   CallTime DATETIME NOT NULL DEFAULT GETDATE(),
   CallerPhoneNumber CHAR(10) NOT NULL
)
-- This table will hold our "tickets" (or cases).
CREATE TABLE dbo.Tickets
(
   ID INT IDENTITY(1, 1) NOT NULL,
   CreatedTime DATETIME NOT NULL DEFAULT GETDATE(),
   Subject VARCHAR(250) NOT NULL,
   Notes VARCHAR(8000) NOT NULL,
   Completed BIT NOT NULL DEFAULT 0
)
-- This table will link a phone call with a ticket.
CREATE TABLE dbo.PhoneCalls_Tickets
(
   PhoneCallID INT NOT NULL,
   TicketID INT NOT NULL
)

8
Было бы лучше и понятнее, если бы вы добавили ограничения первичного и внешнего ключей.
Ашиш К Гупта
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.