Вопрос

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

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

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

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

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

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

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Это называется "SubClassing"

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top