Если у меня есть две таблицы в SQL с отношением многие-много, нужно ли создавать дополнительную таблицу? - PullRequest
4 голосов
/ 24 января 2010

Для примера возьмем эти таблицы.

Item
    id
    description
    category

Category
    id
    description 

Элемент может принадлежать ко многим категориям, а категория, очевидно, может быть присоединена ко многим элементам.

Как база данных будет создана в этой ситуации? Я не уверен. Кто-то сказал, создать третью таблицу, но нужно ли это делать? Я буквально делаю

создать таблицу бла бла

для третьего стола?

Ответы [ 3 ]

4 голосов
/ 24 января 2010

Да, вам нужно создать третью таблицу с сопоставлениями идентификаторов, что-то со столбцами вроде:

 item_id     (Foreign Key)
 category_id (Foreign Key)

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

Думайте об этой таблице как о перечне всех отображений между Предметами и Категориями. Это лаконично и легко справиться.

edit: удаленный (ненужный) первичный ключ.

3 голосов
/ 24 января 2010

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

Item
    id primary key
    description

Category
    id primary key
    description

ItemCategory
    itemid     foreign key references Item(id)
    categoryid foreign key references Category(id)

Вам не нужна категория в таблице Предметов, если у вас нет какой-либо привилегированной категории для предмета, который, кажется, не имеет место здесь. Я также не большой поклонник введения ненужных первичных ключей, когда на присоединяемой таблице уже есть «настоящий» уникальный ключ. Тот факт, что идентификаторы элементов и категорий уже являются уникальными, означает, что вся запись для таблицы ItemCategory также будет уникальной.

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

  • Itemid
  • CategoryID
  • (Itemid, CategoryID)
  • (CategoryID, Itemid)

в зависимости от запросов, которые вы используете для объединения данных (и один из составных индексов будет первичным ключом).

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

create table Item (
    id            integer       not null primary key,
    description   varchar(50)
);
create table Category (
    id            integer       not null primary key,
    description   varchar(50)
);
create table ItemCategory (
    itemid        integer       references Item(id),
    categoryid    integer       references Category(id),
    primary key   (itemid,categoryid)
);

Есть и другие вещи, которые вы должны учитывать, такие как превращение столбцов идентификаторов в столбцы идентификаторов / автоинкрементов, но это не имеет прямого отношения к рассматриваемому вопросу.

2 голосов
/ 24 января 2010

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

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

Здесь вступает таблица соединения - для каждого отношения между Item и Category отношение представляется в таблице соединения в виде пары: Item.id x Category.id.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...