Правильные внешние ключи для MS SQL Server 2005 без УНИКАЛЬНЫХ ограничений? - PullRequest
1 голос
/ 23 февраля 2011

У меня есть две таблицы (MS SQL Server 2005) с существующим приложением (изменения БД, кроме индексов и т. Д., Не допускаются).

Две таблицы:

ActivityDetails (Primary table)
    ActivityDetailkey (Primary key)

SubActivities (Child table)
    ActivityDetailKey (Refers to ActivityDetails)

Теперь нет никаких ограничений на SubActivities для ActivityDetailKey.В принципе, для КАЖДОЙ ActivityDetail строки может быть МНОГИЕ SubActivities строк, и ничто не мешает пользователю удалить строку ActivityDetails и оставить сироту SubActivities.

Предполагалось, чтонекоторые "мягкие блокировки" в приложении, которые могли бы предотвратить это, но это не работает, и я хотел бы также повысить уровень целостности на уровне базы данных.

Но я не могу добавить внешний ключ, потому чтостолбец SubActivities ActivityDetailKey не уникален.

Как запретить людям удалять строки ActivityDetails, если присутствуют дети?

Спасибо

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

Прошу прощения за сложность.Таблица SubActivities фактически называется TEDetailSubActivities.Я изменил его в вопросе так, чтобы его было легче читать.

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

https://gist.github.com/840479

Я ценю любую помощь.

Ответы [ 2 ]

2 голосов
/ 23 февраля 2011

Вы можете иметь внешний ключ, даже если он продублирован в дочерней таблице, вы должны добавить опцию WITH CHECK, например:

ALTER TABLE [dbo].[SubActivities]  WITH CHECK ADD  CONSTRAINT [FK_SubActivities_ActivityDetails] FOREIGN KEY([ActivityDetailkey])
REFERENCES [dbo].[ActivityDetails ] ([ActivityDetailkey])

Надеюсь, это поможет!

2 голосов
/ 23 февраля 2011

Звучит так, будто вы пытаетесь настроить внешний ключ неправильно - если в SubActivities несколько строк с одинаковым значением ActivityDetailKey, и это ссылки на первичный ключ в ActivityDetails, то должно работать следующее(на основе вашей опубликованной схемы и теперь протестировано):

ALTER TABLE TEDetailSubActivities ADD CONSTRAINT FK_TEDetailSubActivities_ActivityDetails FOREIGN KEY
      (ActivityDetailKey) references dbo.ActivityDetails (ActivityDetailKey)

предыдущая версия, основанная на именах таблиц в сообщении:

ALTER TABLE SubActivities ADD CONSTRAINT FK_SubActivities_ActivityDetails FOREIGN KEY
      (ActivityDetailKey) references ActivityDetails (ActivityDetailKey)

Не существует требования уникальности для столбца ActivityDetailKey в SubActivities.

Как есть, это остановит удаление строк из ActivityDetails, если в SubActivities есть строки, ссылающиеся на них.Если, с другой стороны, вы хотите, чтобы приложение могло продолжать удаление, но не оставлять осиротевшие строки в SubActivities, добавьте ON DELETE CASCADE после последней закрывающей скобки выше.


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

create table ActivityDetails (
    ActivityDetailkey int not null Primary key
)
go
create table SubActivities (
    ActivityDetailKey int not null
)
go

Вздох.Если вы собираетесь настаивать на использовании конструкторов SSMS:

  • Щелкните правой кнопкой мыши SubActivities, выберите «Дизайн».
  • Нажмите кнопку панели инструментов «Отношения»
  • Нажмите «Добавить»
  • Нажмите «...» напротив свойства «Спецификация таблиц и столбцов»
  • В раскрывающемся списке «Таблица первичных ключей» выберите «ActivityDetails»
  • В приведенной ниже сетке выберите ActivityDetailKey с обеих сторон
  • Нажмите «ОК», «Закрыть», кнопку «Сохранить» на панели инструментов и (при необходимости) «Да» для предупреждения о сохранении
  • Закрыть конструктор.
...