Використання декількох сторонніх ключів на одному стовпчику в 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ᵀᴹ - Зрозумів. Дякуємо, що
вияснили

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.