Внешний ключ, ссылающийся на несколько таблиц

У меня есть столбец с уникальным идентификатором, который может ссылаться на одну из четырех разных таблиц. Я видел, как это делается двумя способами, но оба кажутся плохой практикой.

Сперва я'мы видели один столбец ObjectID без явного объявления его в качестве внешнего ключа для конкретной таблицы. Тогда вы можете просто вставить любой уникальный идентификатор, который вы хотите в нем. Это означает, что вы потенциально можете вставить идентификаторы из таблиц, которые не являются частью 4 таблиц, которые я хотел.

Во-вторых, поскольку данные могут поступать из четырех разных таблиц, яМы также видели, как люди делают 4 разных внешних ключа. При этом система опирается на столбец ONE и ONLY ONE, значение которого не равно NULL.

Какие'лучший подход к этому? Например, записи в моей таблице могут ссылаться на больницы (ID), клиники (ID), школы (ID) или университеты (ID) ... но ТОЛЬКО на эти таблицы.

Спасибо!

 lc.09 нояб. 2012 г., 18:35
Возможно связанные и полезные:stackoverflow.com/a/5001664/44853
 Jake09 нояб. 2012 г., 17:43
Хорошо что'в таблице зданий? ObjectID или четыре отдельных столбца? Я вернулся к той же проблеме? Остальные четыре таблицы уже существуют.
 lc.09 нояб. 2012 г., 17:27
Есть один ключ, который ссылается на здания (ID) вместо этого.
 lc.09 нояб. 2012 г., 17:49
Либо просто удостоверение личности; идентификатор и TypeID; или лучше всего это ID, TypeID и все столбцы, общие для больниц, клиник, школ и университетов. Тогда каждая из этих таблиц ID - это на самом деле BuildingID, уникальный для всех четырех таблиц.
 marc_s09 нояб. 2012 г., 18:06
По крайней мере, если у вас есть четыре отдельных FK, вы можете настроить и обеспечить надлежащую ссылочную целостность, используя ограничения внешнего ключа - can 'Это невозможно, если у вас есть один столбец, ссылающийся на одну из четырех разных таблиц ....

Ответы на вопрос(3)

Позволять'начать с концептуального уровня. Если мы думаем о больницах, клиниках, школах и университетах как о классах предметных сущностей, существует ли суперкласс, который обобщает их все? Там, вероятно, есть. Я'Я не собираюсь говорить вам, что это такое, потому что я неЯ не понимаю вашу тему так же хорошо, как вы. Но я'Я собираюсь действовать так, как будто мы можем назвать их всех "институты»и относиться к каждому из четырех как к подклассам учреждений.

Как отметили другие респонденты, расширение и наследование классов / подклассов не встроено в большинство систем реляционных баз данных. Но есть много помощи, если вы знаете правильные модные слова. То, что следует, предназначено, чтобы научить вас модным словам, в базе данных жаргон. Вот краткое изложение модных слов:Обобщение ЭР ","ER специализация ","Наследование в одной таблице ","Наследование таблицы классов ","Общий первичный ключ ".

Находясь на концептуальном уровне, ER моделирование является хорошим способом понимания данных на концептуальном уровне. В ER моделировании есть понятие "ER Обобщение "и аналог концепции "ЭР Специализация " что параллельный мыслительный процесс, который я только что представил выше каксуперкласс / подкласс», ER специализация расскажет вам, как составить схему подклассов, но это не такРасскажу, как их реализовать.

Затем мы переходим от концептуального уровня к логическому уровню. Мы выражаем данные в виде отношений или, если хотите, таблиц SQL. Есть несколько методов для реализации подклассов. Один называетсяНаследование одного стола ", Другой называетсяНаследование таблицы классов ", В связи с наследованием таблиц классов существует еще один метод, который называется «Общий первичный ключ ".

Продвигаясь в вашем случае с наследованием таблиц классов, мы сначала спроектируем таблицу под названием "институты»с полем Id, полем имени и всеми полями, относящимися к учреждениям, независимо от того, к какому из четырех типов они относятся. Такие вещи, как поля почтового адреса, например. Опять же, вы понимаете свои данные лучше, чем я, и вы можете найти поля, которые есть во всех четырех ваших существующих таблицах. Мы заполняем поле id обычным способом.

Далее мы разрабатываем четыре таблицы под названием "Больницы ","Клиника ","Школы", а также "Университеты», Они будут содержать поле идентификатора плюс все поля данных, которые относятся только к такого рода учреждению. Например, больница может иметь "вместимость кровати ", Опять же, вы понимаете свои данные лучше, чем я, и вы можете понять их из полей в ваших существующих таблицах, которые несделать это в таблице учреждений.

Это где "общий первичный ключ входит. Когда новая запись сделана в "институты»мы должны сделать новую параллельную запись в одну из четырех специализированных таблиц подкласса. Но мы неt использовать какую-то функцию автонумерации для заполнения поля id. Вместо этого мы помещаем копию поля id изинституты» таблица в поле id таблицы подкласса.

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

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

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

Уважать "ER специализация ","Наследование таблицы классов ","Общий первичный ключ ", и возможно "Наследование одного стола " в Интернете, и здесь, в SO. Здесь, в SO, есть теги для большинства этих концепций или методов.

Возможно, вы захотите рассмотреть модель данных Type / SubType. Это очень похоже на класс / подклассы в объектно-ориентированном программировании, но гораздо более неудобно для реализации, и ни одна СУБД (о которой я знаю) изначально не поддерживает их. Общая идея такова:

Вы определяете тип (здание), создаете для него таблицу, присваиваете ей первичный ключВы определяете два или более подтипа (здесь, Больница, Клиника, Школа, Университет), создаете таблицы для каждого из них, делаете первичные ключи… но первичные ключи также являются внешними ключами, которые ссылаются на таблицу BuildingВаш стол с одним «ObjectType» столбец теперь может быть построен с помощью внешнего ключа на таблицу здания. Вы'Мне нужно объединить несколько таблиц, чтобы определить, что это за здание, но выЯ должен сделать это в любом случае. Это или хранить избыточные данные.

Вы заметили проблему с этой моделью, верно? Какие's чтобы здание не имело записей в двух или более таблицах подтипов? Рад, что вы спросили:

Добавьте столбец, возможно, «BuildingType», для Building, скажем char (1) с допустимыми значениями {H, C, S, U}, указывающими (duh) тип здания.Создайте уникальное ограничение для BuildingID + BuildingTypeИмейте столбец BulidingType в подтаблицах. Установите для него проверочное ограничение, чтобы его можно было установить только на значение (H для таблицы Больниц и т. Д.) Теоретически это может быть вычисляемый столбец; на практике это победилоработать из-за следующего шага:Создайте внешний ключ, чтобы связать таблицы, используя оба столбца

Вуаля: Учитывая, что строка СТРОИТЕЛЬСТВО установлена с типом H, запись в таблице SCHOOL (с типом S) не может быть установлена для ссылки на это здание

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

На самом деле, большой вопрос: стоит ли это делать? Если имеет смысл реализовать четыре (или более, с течением времени) типа здания как тип / подтип (дополнительные преимущества нормализации: одно место для адреса и другие атрибуты, общие для каждого здания, с характерными для здания атрибутами, хранящимися в подтаблицах), это может стоить дополнительных усилий по созданию и обслуживанию. Если нет, то выВернемся к исходной точке: логическая модель, которую сложно внедрить в среднюю современную СУБД.

 Branko Dimitrijevic09 нояб. 2012 г., 23:43
+1 Хороший ответ, кроме как в дополнение к соблюдениюисключительность ребенка (как вы объяснили), также возможно декларативно обеспечить соблюдениеприсутствие ребенка, но это потребуетмного гимнастики с круговыми и отложенными ФК и, вероятно, не стоит усилий.
 Branko Dimitrijevic12 нояб. 2012 г., 17:30
Предполагая, что вы включаетеотсроченный ограничения в определенииобычный» Из-за ограничений целостности можно обеспечить существование дочерних элементов исключительно с помощью декларативных средств (взгляните на мою ссылку). Я выиграл'спорить этодолжен быть сделано на практике, но это возможно.
 Philip Kelley12 нояб. 2012 г., 16:02
Используя только обычные инструменты декларативной ссылочной целостности, я нене думаю, что этоВозможно обеспечить существование дочерней записи. Вы можете ВСТАВИТЬ ЗДАНИЕ и никогда не делать дочернюю запись. В крайнем случае, вы можете поместить проверочное ограничение (или таблицу поиска + внешний ключ) в BUILDING.BuildingType и добавить триггер, который всегда создает строку по умолчанию в соответствующей подтаблице, и, как вы говорите, это выглядит как перебор. Сложно, неловко, и, вероятно, почему крупные поставщики не имеютЯ нашел время для его реализации.
 Philip Kelley13 нояб. 2012 г., 15:54
Правда. Другим вариантом (по крайней мере в SQL Server) являются триггеры INSTEAD OF. Определите один для каждой подтаблицы и выполните вставки в подтаблицы. Безразлично»Обеспечивает наличие подтипа, но облегчает его ввод.

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

Ваш ответ на вопрос