#sql #sql-server #sql-server-2008 #sql-server-2008-r2
#sql #sql-сервер #sql-server-2008 #sql-server-2008-r2
Вопрос:
Дано четыре таблицы:
CREATE TABLE LIST_A (
A INT,
PRIMARY KEY (A)
)
CREATE TABLE LIST_B (
A INT,
B INT,
PRIMARY KEY (A, B),
FOREIGN KEY (A) REFERENCES LIST_A (A)
)
CREATE TABLE LIST_C (
C INT,
A INT,
PRIMARY KEY (C),
FOREIGN KEY (A) REFERENCES LIST_A (A)
)
CREATE TABLE LIST_D (
C INT,
D INT,
B INT,
PRIMARY KEY (C, D),
FOREIGN KEY (C) REFERENCES LIST_C (C)
)
Я хочу добавить еще одно ограничение: учитывая строку в LIST_D
, чей первичный (C0,D0)
ключ, и его родительскую строку в LIST_C
, чей первичный ключ C0
, пара (LIST_C.A, LIST_D.B)
должна ссылаться LIST_B (A, B)
. Как мне реализовать это в SQL Server 2008 R2?
Комментарии:
1. У вас не может быть внешнего ключа, составленного из столбцов из двух разных таблиц. Внешний ключ всегда является связующим звеном между одной таблицей и другой, а не между двумя (или более) таблицами на одном конце и другой на другом конце
2. @marc_s: Я не знаю, как выразить это простыми словами, поэтому я просто надеюсь, что смогу прояснить свою точку зрения. Думайте о
LIST_A
иLIST_C
как о таблицах «заголовков», а оLIST_B
иLIST_D
как об их соответствующих «деталях». Я хочу, чтобы каждыйC
заголовок был связан сA
заголовком; и я также хочу, чтобы каждаяD
деталь, связанная с конкретнымC
заголовком, была связана сB
деталью, связанной с тем жеA
заголовкомC
, с которым связан заголовок.3. Неважно, как вы это говорите: у вас не может быть внешнего ключа, состоящего из двух столбцов из двух разных таблиц…
4. @marc_s: Есть ли альтернативный способ выразить идею, которую я пытаюсь смоделировать? Я знаю, что мог бы заставить его работать следующим неэлегантным способом: пусть
A
будет частьюLIST_C
первичного ключа. Затем, чтобы сохранить связь междуLIST_C
иLIST_D
, добавьтеA
в качестве поляLIST_D
. Наконец, чтобы сохранить уникальностьC
inLIST_C
, добавьтеUNIQUE
ограничение на это поле. // Но это явно взлом дизайна, и, учитывая масштаб моего проекта, я должен поддерживать его в чистоте, по крайней мере, на уровне дизайна.
Ответ №1:
Я думаю, что важно (как для нас, так и для вас) знать цель добавления дополнительного внешнего ключа?
В зависимости от конкретной проблемы, которую вы пытаетесь решить (проверка данных при вводе, каскадные удаления и т. Д.), И гибкости, которой вы обладаете для их решения (возможность или невозможность изменять структуру данных), вы можете реализовать логические ограничения с помощью триггеров. Мы используем этот подход в тех случаях, когда нам просто нужно перехватить граничные условия, которые должны возникать редко, если вообще когда-либо.
Если триггеров недостаточно для вашей ситуации и требуются внешние ключи, то единственный оставшийся у вас вариант (без изменения дизайна всех таблиц) — сохранить LIST_C.A в LIST_D, а затем создать FKey обратно в LIST_B .
Другой вариант — перепроектировать его таким образом, чтобы у вас были промежуточные таблицы, содержащие соответствующие ссылки между всеми таблицами, но, похоже, это нежелательно.