Связи с базой данных T-SQL PK с тем же именем, что и у FK?

StackOverflow https://stackoverflow.com/questions/1622638

Вопрос

Сценарий

У меня есть 3 таблицы базы данных.Один предназначен для изображений, а два других - для людей и мест.Поскольку у каждого человека может быть много изображений и в каждом месте может быть много изображений, я хочу иметь отношение "ОДИН КО МНОГИМ" как между людьми, так и между изображениями, а также местами и изображениями.

Вопрос

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

Помощь очень ценится.

С уважением,

Редактировать:

Причина, по которой требуется иметь только одну таблицу изображений, заключается в том, что каждое изображение ссылается только на одну другую таблицу.Помимо этого, я использовал приведенный здесь пример с двумя таблицами, на самом деле база данных, которую я буду использовать, будет содержать 20 таблиц, поэтому я хотел знать, все еще возможно ли использовать ОДНУ ТАБЛИЦУ ИЗОБРАЖЕНИЙ ДЛЯ 20 ОТНОШЕНИЙ "ОДИН КО МНОГИМ"?

Это было полезно?

Решение

Редактировать

Если одно изображение когда-либо принадлежало только одной из двадцати таблиц, этот дизайн может сработать:

People (PersonId, Name)
Places (PlaceId, Name)
Dogs (DogId, Breed)
Doors (DoorId, Height, Width)
Images (ImageId, ImageBinary, OwnerId, OwnerTable)

Где OwnerTable - это имя или код таблицы, к которой принадлежит OwnerId.

Это сэкономило бы вам 20 FKS в таблице изображений или 20 ассоциативных таблиц.Затем в соединениях вы должны указать OwnerTable, в зависимости от таблицы, к которой вы присоединяетесь.

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

/РЕДАКТИРОВАТЬ

Вам нужно 5 таблиц, а не 3:

People (PersonId, Name)
Places (PlaceId, Name)
Images (ImageId, ImageBinary)
ImagesPeople (ImageId, PersonId)
ImagesPlaces (ImageId, PlaceId)

Вы можете называть поля как угодно.Люди.Идентификатор, ImagesPeople.Идентификатор пользователя и т.д.

Но чего вы не можете сделать, так это чего-то подобного:

People (PersonId, Name)
Places (PlaceId, Name)
Images (ImageId, ImageBinary, PlaceOrPersonId)

Что ж, вы можете, но база данных не поможет вам обеспечить соблюдение взаимосвязи или сообщить вам, к какой таблице принадлежит FK.Откуда тебе знать?Существуют хитрые обходные пути, такие как изменение приращений идентификатора в шахматном порядке, добавление столбца типа к изображениям или использование идентификаторов GUID.

В качестве альтернативы:

Things (ThingId PK, Type)
People (ThingId PK/FK, Name, Age)
Places (ThingId PK/FK, Name, LatLon)
Images (ImageId PK, ImageBinary, ThingId FK)

Вы также могли бы сделать Изображения "Вещью".Иногда вы видите подобные рисунки.Это дает вам ссылочную целостность, но не эксклюзивность типа.У вас мог бы быть один и тот же ThingId в Людях, местах и изображениях, и базе данных было бы все равно.Вам пришлось бы самому закодировать это правило.

Редактировать:по предложению Сайлон Кэт, сценарий 4:

People (PersonId, Name)
Places (PlaceId, Name)
PeopleImages (PeopleImageId, ImageBinary)
PlaceImages (PlaceImageId, ImageBinary)

Здесь изображения принадлежат исключительно одному человеку или месту.Аналогично версии 2, но с объявленными внешними ключами.Это может иметь некоторые преимущества в производительности по сравнению с дизайном из 5 таблиц, поскольку требуется меньше соединений.Вы теряете "Изображение" как отдельную сущность, заменяясь "Изображением людей" и "Изображением места".

Другие советы

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

Теперь технически вы можете называть свои индексы и таблицы как угодно, что не является зарезервированным словом и еще не использовалось, X, Y, Z12345 и WOBBLY - все допустимые имена для индекса.

Однако на практике лучше всего следовать соглашению об именовании, которое указывает на то, что хранится и для чего.Таким образом, таблицы PEOPLE_X_IMAGES и PLACES_X_IMAGES были бы хорошей идеей в вашем случае.На самом деле вам не нужно ничего о людях или местах в таблице фактических изображений.Аналогично, вам ничего не нужно об изображениях в таблицах "ЛЮДИ" и "МЕСТА".

Теоретически вы могли бы добавить два внешних ключа к таблице изображений, один для людей и один для мест.Тогда вы могли бы разрешить значения null и join для соответствующих столбцов при выполнении запроса.Однако это не слишком удачное решение, потому что как будет выглядеть эта таблица, когда у вас есть 14 таблиц, которые нужно объединить с ней?

Если вы не собираетесь использовать GUID, тогда я предлагаю вам настроить это как "многие ко многим" ради следующего парня, который должен это понять.

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

Как насчет

Person (PersonId PK, Name, ImageId FK)
Image (ImageId PK, Name)
Place (PlaceId PK, Name, ImageId FK)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top