Составная таблица ссылок на внешние ключи - PullRequest
2 голосов
/ 06 ноября 2008

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

В основном у меня есть две таблицы: tblSystemItems и tblClientItems. У меня есть третья таблица, в которой есть столбец, который ссылается на «Элемент». Проблема в том, что этот столбец должен ссылаться либо на системный элемент, либо на элемент клиента - не имеет значения, какой именно. Системные элементы имеют ключи в диапазоне 1..2 ^ 31, в то время как клиентские элементы имеют ключи в диапазоне -1 ..- 2 ^ 31, поэтому столкновений никогда не будет.

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

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

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

Ответы [ 6 ]

1 голос
/ 10 ноября 2008

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

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

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

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

В итоге я создал только одну таблицу Items. У элементов есть битовый столбец с именем «SystemItem», который определяет очевидное. В моей базе данных разработки / системы у меня есть PK как int int (1,1). После того, как таблица была создана в клиентской базе данных, ключ идентификации изменяется на (-1, -1). Это означает, что элементы клиента уходят в минус, в то время как системные элементы уходят в плюс.

Для синхронизации я в основном игнорирую что-либо с (SystemItem = 1) при синхронизации остальных, используя IDENTITY INSERT ON. Таким образом, я могу синхронизироваться, полностью игнорируя элементы клиента и избегая коллизий. Я также могу ссылаться только на одну таблицу «Элементы», которая охватывает как клиентские, так и системные элементы. Единственное, что нужно иметь в виду, это исправить стандартный кластеризованный ключ, чтобы он убирался, чтобы избежать всех видов реструктуризации страницы, когда клиент вставляет новые элементы (обновления клиента по сравнению с обновлениями системы, как 99% / 1%).

0 голосов
/ 11 ноября 2008

У меня похожая ситуация в базе данных, которую я использую. У меня есть «ключ-кандидат» в каждой таблице, которую я называю EntityID. Затем, если есть таблица, которая должна ссылаться на элементы более чем в одной из других таблиц, я использую EntityID для ссылки на эту строку. У меня есть таблица Entity для перекрестной ссылки на все (так что EntityID является первичным ключом таблицы Entity, а все остальные EntityID являются FK), но я не часто использую таблицу Entity.

0 голосов
/ 06 ноября 2008

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

0 голосов
/ 06 ноября 2008

Добавьте таблицу с именем Items с PK ItemiD, и один столбец с именем ItemType = "System" или "Client" затем будет иметь таблицу PK ClientItems (с именем ClientItemId) и PK SystemItems (с именем SystemItemId), которые также будут FKs для элементов. ItemId, (Эти отношения являются отношениями от нуля до одного (0-1)

Тогда в вашей третьей таблице, которая ссылается на элемент, просто поместите ограничение FK на элемент itemId в этой дополнительной таблице (Items) ...

Если вы используете хранимые процедуры для реализации вставок, просто сохраните процедуру, которая вставляет элементы, сначала вставьте новую запись в таблицу «Элементы», а затем, используя автоматически сгенерированное значение PK в этой таблице, вставьте фактическую запись данных в либо SystemItems, либо ClientItems (в зависимости от того, какой он есть) как часть одного и того же хранимого вызова proc, используя автоматически сгенерированное (идентификационное) значение, которое система вставила в столбец ItemId таблицы Items.

Это называется "подклассом"

0 голосов
/ 06 ноября 2008

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

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

С немного большим количеством bakcground / context, вероятно, легче определить оптимальное решение.

0 голосов
/ 06 ноября 2008

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

Третья таблица имеет FK to tblItems. В некотором смысле tblItems является родителем двух других таблиц элементов. Для запроса элемента необходимо создать JOIN между tblItems, tblSystemItems и tblClientItems.

[РЕДАКТИРОВАТЬ-для комментария ниже] Если tblSystemItems и tblClientItems контролируют свои собственные PK, то вы все равно можете позволить им. Возможно, вы сначала вставите в tblSystemItems, а затем вставите в tblItems. Когда вы реализуете структуру наследования с помощью такого инструмента, как Hibernate, вы в итоге получаете что-то вроде этого.

...