Использование нескольких внешних ключей в одном столбце в SQL Server


10

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

введите описание изображения здесь

Ответы:


12

Нет необходимости иметь избыточные ограничения, которые различаются только по имени. Точно так же нет необходимости иметь избыточные индексы, которые отличаются только по имени. Оба добавляют накладные расходы без значения.

Ядро базы данных SQL Server не мешает вам сделать это. Хорошие соглашения об именах (например, FK_ReferencingTable_ReferencedTable) могут помочь защитить человека от таких ошибок.


17

SQL Server позволяет делать много глупостей.

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

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

(Как в примере ниже)

CREATE TABLE T1(
    T1_Id INT PRIMARY KEY CLUSTERED  NOT NULL,
    Filler CHAR(4000) NULL,
) 

INSERT INTO T1 VALUES (1, '');

CREATE TABLE T2(
    T2_Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
    T1_Id INT NOT NULL CONSTRAINT FK REFERENCES T1 (T1_Id), 
    Filler CHAR(4000) NULL,
)


ALTER TABLE T1 ADD CONSTRAINT
    UQ_T1 UNIQUE NONCLUSTERED(T1_Id) 


/*Execution Plan uses clustered index*/ 
INSERT INTO T2 VALUES (1,1) 

ALTER TABLE T2  WITH CHECK ADD  CONSTRAINT FK2 FOREIGN KEY(T1_Id)
REFERENCES T1 (T1_Id)    

ALTER TABLE T2 DROP CONSTRAINT FK

/*Now Execution Plan now uses non clustered index*/    
INSERT INTO T2 VALUES (1,1)    

DROP TABLE  T2, T1;

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


Может ли транзакция использоваться для обеспечения того же обновления без пропусков? Возможно, этот нетранзакционный метод лучше благодаря меньшей блокировке?
Бинки

13

Не имеет смысла иметь одинаковые ограничения внешнего ключа. То есть для тех же столбцов и ссылки на одну и ту же таблицу и столбцы.

Это как иметь один и тот же чек 2 или более раз.


-Не согласен. Может быть шанс, что основной таблице понадобятся две отдельные проверки. Ниже приведен пример того, как отправитель и получатель абсолютно разные - stackoverflow.com/questions/40400483/…
trex

@trex, ты говоришь о чем-то другом. Вопрос здесь гласит: «Я хочу знать, в чем польза наличия нескольких внешних ключей, которые определены в одном столбце и ссылаются на один и тот же столбец в другой таблице ».
ypercubeᵀᴹ

@ ypercubeᵀᴹ - Понял. Спасибо за разъяснение
trex

6

По той же причине, по которой вы можете создать 50 индексов в одном столбце, добавить второй файл журнала, установить максимальный объем памяти сервера в 20 МБ ... большинство людей не будут делать такие вещи, но иногда могут быть законные причины делать это, так что нет выгода в создании накладных расходов в двигателе, чтобы добавить проверки против вещей, которые просто опрометчивы.


2

Походит на сине-зеленую вещь.

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

Мы хотим временно создать дополнительный внешний ключ CHECK WITH NOCHECKи ON UPDATE CASCADE ON DELETE SET NULL; то, что это делает, - это рабочий внешний ключ, но существующие строки не проверяются при создании ключа.

Позже после очистки всех строк, которые должны совпадать, мы создадим новый внешний ключ без каких-либо параметров команды (по умолчанию CHECK WITH CHECKэто то, что вы обычно хотите) и удалите временный внешний ключ.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.