Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > СУБД, общие вопросы > Организация связи многие-ко-многим


Автор: Scarlett 21.12.2007, 19:43
необходим срочный ответ! smile

при создании структуры БД возник небольшой спор по такой ситуации:

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

для промежуточной таблицы эти два форейн ки уже определяют ее первичный ключ
или все-таки для этой таблицы надо тоже выделять отдельный первичный ключ?

 я считаю, что так как таблица является связующей, то у нее 2 колонки, которые хранят форейн ки и вместе определяют первичный ключ

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

вот и вопрос: определять новый первичный ключ или нет? В промежуточной таблице никакая другая информация не хранится!

Автор: skyboy 21.12.2007, 21:32
Цитата(Scarlett @  21.12.2007,  18:43 Найти цитируемый пост)
мне же говорят что надо создавать еще одну колонку, которая будет хранить первичный ключ

скорее всего, говорящий человек ошибается в понятиях: путает теплое и мягкое.
первичный ключ - то, что однозначно идентифицирует запись.
зачастую, в таблице, хранящей связь многие-ко-многим сочетание значений полей-ссылок на другие таблицы уже уникально. потому это сочетание и может быть первичным ключом(в модели - точно будет, для использования СУБД тоже можно указать - будет составной естественный http://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B2%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BB%D1%8E%D1%87). Можно добавить дополнительно автоинкрементное поле, которое объявить первичным ключом таблицы. Это будет простой синтетический(искусственный) первичный ключ.
Слегка подытожу: есть составной(из нескольких полей) и простой(из одного поля) первичный ключ, а есть естественный(уникальность определяется логикой модели, точно так же, как ДНК абсолютно уникально безо всяких паспортных номеров - даже у клонов за счет мутации генотип будет отличен) и искусственный(автоинкрементное поле) первичный ключ.
Так вот: в настоящий момент(если сочетание значений в каждой записи таблицы уникально) у тебя - составной естественный первичный ключ. А тебе предлагают просто синтетический первичный ключ.
----
Совет: если у тебя связь(которая имеет форму "многая-ко-многим") может иметь дополнительные аттрибуты и связи(т.е. на связь между сущностями ссылаются другие связи), то лучше ввести в третью твою таблицу синтетический простой первичный ключ, что не усложнять запросы объединениями таблиц по двум-трем полям. Если связь аттрибутов/зависимостей не может имет в пределах модели, вполне можно обойтись только имеющимимся полями - не стОит без нужды плодить не используемые данные.

Автор: Deniz 22.12.2007, 08:24
В основном поддерживаю skyboy, про искусственный и естественный все правильно, но споры эти идут давно, и у всех есть свои мнения на этот счет. От себя добавлю, что система должна иметь возможность масштабирования, и здесь
Цитата(skyboy @  22.12.2007,  00:32 Найти цитируемый пост)
Совет: если у тебя связь(которая имеет форму "многая-ко-многим") может иметь дополнительные аттрибуты и связи(т.е. на связь между сущностями ссылаются другие связи), то лучше ввести в третью твою таблицу синтетический простой первичный ключ, что не усложнять запросы объединениями таблиц по двум-трем полям.

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

PS: на www.ibase.ru есть http://www.ibase.ru/devinfo/NaturalKeysVersusAtrificialKeysByTentser.html  очень старая, но кое-что можно для себя извлечь. 

Автор: Scarlett 22.12.2007, 17:24
спасибо за полный ответ smile

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

хотя я не знаю, что вдруг взбредет в голову заказчикам, поэтому, наверное, все-таки прийдется его создавать...  smile 

Автор: skyboy 22.12.2007, 18:53
если вопрос решен, помечаем его решенным(кликаем по надписи "пометить вопрос решенным" справа вверху над первым сообщением в теме).

Автор: LSD 22.12.2007, 18:55
Цитата(Scarlett @  21.12.2007,  19:43 Найти цитируемый пост)
или все-таки для этой таблицы надо тоже выделять отдельный первичный ключ?

Я считаю что такой ключ не нужен, т.к. это ухудшает производительность, а плюсов не дает.

Синтетический ПК создавался для того, чтобы абстрагироваться от пользовательских данных. Например если у нас ПК образуется по полям ФИО, то изменение ФИО (например опечатались при вводе) потребует изменения всех записей ссылающихся на данную. А синтетический ПК не как не связан с пользовательскими данными, и не должен никогда изменяться. 
В данном случае ПК тоже не будет никак связан с пользовательскими данными, и проблем ЕК в нем нет.

Автор: Deniz 24.12.2007, 07:58
Цитата(LSD @  22.12.2007,  21:55 Найти цитируемый пост)
В данном случае ПК тоже не будет никак связан с пользовательскими данными, и проблем ЕК в нем нет. 
 не совсем так.
Вот ключевая фраза:
Цитата(Scarlett @  22.12.2007,  20:24 Найти цитируемый пост)
хотя я не знаю, что вдруг взбредет в голову заказчикам...


Представим, что потребовалось хранить период жизни записи-связи.
Например, было:
Код

ID1 ID2
1   2
1   3
нужно сделать:
Код

ID1 ID2 Start End
1   2   01.01.2007 01.07.2007
1   2   01.09.2007 31.12.2007
прикиньте затраты на изменение, при наличии/отсутствии синтетического ключа

Автор: LSD 24.12.2007, 12:45
Цитата(Deniz @  24.12.2007,  07:58 Найти цитируемый пост)
прикиньте затраты на изменение, при наличии/отсутствии синтетического ключа

При таком раскладе конечно - да... 
Но:
1. Это экзотика, такие вещи приходится делать редко.
2. Перестроение базы операция не рядовая и выполняется тоже крайне редко.

Автор: Akina 24.12.2007, 14:24
Цитата(LSD @  24.12.2007,  13:45 Найти цитируемый пост)
 Это экзотика, такие вещи приходится делать редко.

Сплошь и рядом.

Вопрос, как обычно, решается просто - является ли совокупность ссылок на сущности отдельной сущностью, или она только устанавливает связи? Если она является самостоятельной сущностью, она должна иметь первичный ключ. Если нет - достаточно синтетического ключа.

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

Автор: LSD 24.12.2007, 14:32
Цитата(Akina @  24.12.2007,  14:24 Найти цитируемый пост)
Скажем, если таблицу поставщиков и таблицу потребителей по схеме много-ко-многим связывает таблица договоров или рейсов - непременно первичный ключ...

Тогда это уже отдельная сущность, связанная с двумя другими. А тут речь шла о том, что есть связь между двумя сущностями.

Автор: skyboy 24.12.2007, 16:28
Цитата(LSD @  24.12.2007,  13:32 Найти цитируемый пост)
Тогда это уже отдельная сущность, связанная с двумя другими.

не совсем. есть же понятие в ER-диаграммах "relationship-entity"("связующая сущность" в моем переводе) для сущности, не имеющей воплощения в реальном мире, но имеющей в пределах модели дополнительные атрибуты/связи.
но это уже вопрос терминологии.

Автор: Akina 24.12.2007, 16:38
Цитата(LSD @  24.12.2007,  15:32 Найти цитируемый пост)
Тогда это уже отдельная сущность, связанная с двумя другими. А тут речь шла о том, что есть связь между двумя сущностями. 

Так а я о чем! и неважно, есть у нее физический смысл или нет (см. пост skyboy). Ну привел я пример с физическим смыслом... хотите без него? пожалуйста, навскидку - номера телефонов фирмы и список сотрудников. И связующая таблица - по каким телефонам до каких сотрудников можно дозвониться.

Автор: Scarlett 24.12.2007, 19:05
я потому и решила пойти на уступки и создать первичный ключ
так как ситуация с примером, который привел Deniz, может случиться, а может и не быть

таким образом вопрос закрылся smile

Автор: Deniz 25.12.2007, 10:00
Не хотелось добавлять после
Цитата(Scarlett @  24.12.2007,  22:05 Найти цитируемый пост)
таким образом вопрос закрылся

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

Цитата(LSD @  24.12.2007,  15:45 Найти цитируемый пост)
При таком раскладе конечно - да... 
Но:
1. Это экзотика, такие вещи приходится делать редко.
2. Перестроение базы операция не рядовая и выполняется тоже крайне редко. 

Не знаю как у Вас, но это происходит достаточно часто.
PS: как правило такие связи характеризуются не только периодом жизни(который всегда должен быть для истории), но еще дополнительными атрибутами. И если на первый взгляд их не видно, то потом, когда заказчик захочет, будет, как говорил классик, 
Код

... мучительно больно за бесцельно прожитые годы
.

Автор: LSD 25.12.2007, 13:03
Цитата(skyboy @  24.12.2007,  16:28 Найти цитируемый пост)
не совсем. есть же понятие в ER-диаграммах "relationship-entity"("связующая сущность" в моем переводе) для сущности, не имеющей воплощения в реальном мире, но имеющей в пределах модели дополнительные атрибуты/связи.

Я про связь с реальным миром и не говорил. Я говорю про, что - это или отдельная сущность (пусть и связующая) или связь в чистом виде. Для связей в чистом виде собственный СК не нужен.

Автор: Scarlett 25.12.2007, 14:46
Цитата(Deniz @  25.12.2007,  10:00 Найти цитируемый пост)
Scarlett, не описав проблему и предметную область полностью (что это за связь) Вы и получили такие ответы.


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

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





Автор: ZMaximI 26.12.2007, 10:32
Scarlett, вообще-то архитектура многие-ко-многим не предусматривает никаких промежуточных таблиц.
Не следует этого делать, в такой таблице просто нет надобности.

Было бы очень неплохо увидеть структуру таблиц.

Автор: skyboy 26.12.2007, 10:46
Цитата(ZMaximI @  26.12.2007,  09:32 Найти цитируемый пост)
 вообще-то архитектура многие-ко-многим не предусматривает никаких промежуточных таблиц.

если я тебе скажу, что под "промежуточной таблицей" товарищ Scarlett подразумевает таблицу, хранящую собственно связи, ты повторишь свои слова про то, что такая таблица не нужна?  smile 

Автор: ZMaximI 26.12.2007, 10:50
Да, повторю, потому как связи должны храниться в самих таблицах, а не в промежуточной.

Автор: Akina 26.12.2007, 11:10
Цитата(ZMaximI @  26.12.2007,  11:50 Найти цитируемый пост)
связи должны храниться в самих таблицах, а не в промежуточной

Что-то не понял... как это сделать без денормализации?

Автор: ZMaximI 26.12.2007, 12:45
Для этого есть вторичные ключи ....

Автор: Scarlett 26.12.2007, 12:45
Цитата(Akina @ 26.12.2007,  11:10)
Цитата(ZMaximI @  26.12.2007,  11:50 Найти цитируемый пост)
связи должны храниться в самих таблицах, а не в промежуточной

Что-то не понял... как это сделать без денормализации?

вот-вот...
и я о том же smile

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

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

Автор: Akina 26.12.2007, 13:55
Цитата

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

Связи с отношением «многие-ко-многим» создаются в базе данных с помощью промежуточных (связующих) таблиц. Связующая таблица содержит столбцы первичного ключа обеих связываемых таблиц. Столбцы первичного ключа каждой из связываемых таблиц связываются с соответствующими столбцами промежуточной таблицы. В учебной базе данных pubs на Microsoft SQL Server связующей таблицей является таблица titleauthor.

Вот это - понятно... а что Вы разумеете под вторичным ключом, особенно в части хранения его в таблице данных - совершенно неясно.

Автор: ZMaximI 26.12.2007, 14:32
не вижу смысла спорить ....
чуть позже выложу статью, как правильно организовать связь многие-ко-многим, не теорию ВАЗов, а реальную практику ...

Автор: Akina 26.12.2007, 14:38
Цитата(ZMaximI @  26.12.2007,  15:32 Найти цитируемый пост)
чуть позже выложу статью

Ждем... тут выложишь, на форуме? 

Автор: Deniz 26.12.2007, 14:47
Цитата(ZMaximI @  26.12.2007,  17:32 Найти цитируемый пост)
чуть позже выложу статью, как правильно организовать связь многие-ко-многим

Ждем с нетерпением. Очень интересно будет почитать.


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)