powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Два внешних ключа, противоречащих друг другу
9 сообщений из 9, страница 1 из 1
Два внешних ключа, противоречащих друг другу
    #37578575
andy.s
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В базе данных есть таблица "pages", в которой хранится информация о некоторых страницах (можно называть их документами, но это не важно). У каждой страницы есть id, название, ещё много всякой ерунды и поле "тип страницы". Типы страниц хранятся в таблице "page_types": id, название типа и прочее.

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

Получается следующая ситуация. Добавляем таблицу, где будут хранится файлы (имя, размер и прочее). Теперь добавляем еще одну таблицу, где будут хранится группы файлов: (id группы, id типа страницы, название группы). Теперь при добавлении страницы какого-то типа можно сразу вывести названия групп, в которые можно добавить файлы. Но что делать с таблицей самих файлов? Получается, что там нужны как id страницы, так и id группы, в которой этот файл на этой странице находится. Тогда никто не запрещает добавить запись с такими значениями этих полей, при которых эти id соответствуют разным типам страниц (группа 1->тип страницы 1 + страница 8->тип страницы 2).

В чём тут фокус? Вроде пытался рассуждать логически, а получилась какая-то, простите, хрень :D
...
Рейтинг: 0 / 0
Два внешних ключа, противоречащих друг другу
    #37578594
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andy.sПолучается, что там нужны как id страницы, так и id группы, в которой этот файл на этой
странице находится.

Зачем там id страницы? Может существовать файл, привязанный к странице, но без группы?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Два внешних ключа, противоречащих друг другу
    #37578649
andy.s
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovЗачем там id страницы? Может существовать файл, привязанный к странице, но без группы?
А как иначе? Если оставить только id группы, то как узнать, к какой странице привязан файл? Группы не содержат никакой информации о конкретных страницах, там лишь указывается тип страницы.
...
Рейтинг: 0 / 0
Два внешних ключа, противоречащих друг другу
    #37578652
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andy.sГруппы не содержат никакой информации о конкретных страницах, там лишь указывается тип
страницы.

Ну тогда либо контролируй, что файл привязан к правильной странице/группе триггерами, либо
заведи отдельный список групп, привязанных к странице. Или ещё что-нибудь. Это зависит от
того, какие выборки потребуется делать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Два внешних ключа, противоречащих друг другу
    #37578680
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andy.s, продолжайте использовать корректное сокращения - значительно упрощает общение :)

С вашей подачи уже имеем pages, page_types

andy.sДобавляем таблицу, где будут хранится файлы (имя, размер и прочее).
files

andy.s Теперь добавляем еще одну таблицу, где будут хранится группы файлов: (id группы, id типа страницы, название группы).

Не "группы файлов", а "виды групп файлов на конкретных типах страниц": file_group_types (_for_page_types - но это уж слишком длинно).

Ещё раз, file_group_types - потому что это не группы конкретных файлов, а именно названия (типы, виды) для групп файлов в зависимости от типа страницы.

andy.sНо что делать с таблицей самих файлов?
Получается, что там нужны как id страницы, так и id группы, в которой этот файл на этой странице находится. Тогда никто не запрещает добавить запись с такими значениями этих полей, при которых эти id соответствуют разным типам страниц (группа 1->тип страницы 1 + страница 8->тип страницы 2).
В чём тут фокус? Вроде пытался рассуждать логически, а получилась какая-то, простите, хрень :D

а хрень тут в том, что у вас в таблицах "file_groups" и "pages" по привычке суррогатные первичные ключи из одного идентификатора.
А атрибут "ид типа страницы - page_types.id..." мог бы являться частью первичного ключа для этих таблиц "file_groups" и "pages".
И тогда при проектировании таблички files вы бы завели просто два внешних ключа на:
pages (id_page, id_page_type)
file_group_types(id_fgtype, id_page_type)
и у вас бы образовалось в files три атрибута: id_page, id_fgtype, id_page_type. То что id_page_type - это одно и то же поле, и гарантировало бы вам отсутствие херни в виде возможности "добавить запись с такими значениями этих полей, при которых эти id соответствуют разным типам страниц"...
Т.е. чтобы у вас в таблице files не возникло ошибки, напрямую связанной с типом страницы, нужно: внести этот атрибут "тип страницы" в таблицу и внешними ключами обеспечить контроль заполнения этого поля.

Ещё варианты:
1. НЕ обязательно заводить сложные первичные ключи, можно завести дополнительные альтернаивные ключи, оставив суррогатные.
2. Не заводить атрибут и обеспечить целостность триггерами, которые лазят в pages и file_group_types и сверяют совпадение в них id_page_type.
3.
andy.sТеперь при добавлении страницы какого-то типа можно сразу вывести названия групп, в которые можно добавить файлы.

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

П.С.: Рисуйте схему при проектировании - помогает разобраться даже в трёх соснах...
...
Рейтинг: 0 / 0
Два внешних ключа, противоречащих друг другу
    #37578733
andy.s
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
АнатоЛой,

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

Смущает только то, что для каждой записи в таблице files придется таскать за собой это поле name. Места не жалко, но и целостность в принципе не критична, так что можно оставить и начальный вариант, а проверки делать вручную. Пойду брошу монетку :))
...
Рейтинг: 0 / 0
Два внешних ключа, противоречащих друг другу
    #37578745
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andy.s, вы не всё поняли.
пусть остаётся суррогатное поле (id_gt_type). Оно кстати может и не быть суррогатным, а трансформироватья в поле "number_for_sort"
Варианты:
1) или сделайте первичным ключом (id_gt_type, id_page_type) - при этом будет ли id_gt_type уникальным в пределах id_page_type, или уникальным по всей таблице - ваше дело...
2) или оставьте первичным ключом (id_gt_type) и сделайте альтренативный ключ (id_gt_type, id_page_type).

Ключ (первичный или альтернативный) нужен только для того, чтоб на него можно было сослаться внешним ключом из files....
...
Рейтинг: 0 / 0
Два внешних ключа, противоречащих друг другу
    #37578775
andy.s
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
АнатоЛой,

Я понял, просто заметил, что в качестве id_gt_type можно использовать и поле name, которое обязательно должно быть уникальным в пределах id_page_type, т.е. таблица групп может содержать примерно такие строки:

("certificates", 1, "Сертификаты")
("documents", 1, "Документы")

и большего вроде как не надо. В противном случае еще придется делать уникальный индекс на id_page_type+name, если я уж захотел контролировать всё средствами субд :)
...
Рейтинг: 0 / 0
Два внешних ключа, противоречащих друг другу
    #37582311
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andy.sТогда никто не запрещает добавить запись с такими значениями этих полей, при которых эти id соответствуют разным типам страниц
Отчего же, мешает. Если я правильно понял, то:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create table page_types(page_type_id integer not null primary key ...

create table groups(group_id integer not null primary key ...

create table page_type_groups(
  page_type_id integer not null references(page_types), 
  group_id integer not null references(groups)...

create table pages(
  page_id integer not null, 
  page_type_id integer not null references(page_types)...

create table files(
  file_id integer not null primary key,
  page_id integer not null,
  page_type_id integer not null,
  group_id integer not null,
  constraint files_fk1 (page_id, page_type_id) references pages(page_id, page_type_id),
  constraint files_fk2 (page_type_id, group_id) references page_type_groups(page_type_id, group_id)
  ...
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Два внешних ключа, противоречащих друг другу
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]