Korzystanie z wielu kluczy obcych w tej samej kolumnie w SQL Server

10

SQL Server pozwala mi tworzyć wiele kluczy obcych w kolumnie i za każdym razem używając tylko innej nazwy, mogę utworzyć inny klucz odnoszący się do tego samego obiektu. Zasadniczo wszystkie klucze definiują tę samą relację. Chcę wiedzieć, jaki jest pożytek z posiadania wielu kluczy obcych zdefiniowanych w tej samej kolumnie i odwołania do tej samej kolumny w innej tabeli. Jaka jest z tego korzyść, że SQL Server pozwala nam robić coś takiego?

wprowadź opis zdjęcia tutaj

igelr
źródło

Odpowiedzi:

12

Redundantne ograniczenia, które różnią się tylko nazwą, nie przynoszą korzyści. Podobnie nie ma korzyści z posiadania redundantnych indeksów, które różnią się tylko nazwą. Oba dodają koszty ogólne bez wartości.

Aparat bazy danych SQL Server nie powstrzymuje Cię przed tym. Dobre konwencje nazewnictwa z ograniczeniami (np. FK_ReferencingTable_ReferencedTable) mogą pomóc w ochronie przed takimi błędami.

Dan Guzman
źródło
17

SQL Server pozwala ci robić wiele głupich rzeczy.

Możesz nawet utworzyć klucz obcy w kolumnie odwołującej się do samego siebie - pomimo faktu, że nigdy nie można go złamać, ponieważ każdy wiersz spełnia ograniczenia na sobie.

Jednym z przypadków skrajnych, w których możliwość utworzenia dwóch kluczy obcych w tej samej relacji byłaby potencjalnie użyteczna, jest fakt, że indeks używany do sprawdzania poprawności kluczy obcych jest określany w czasie tworzenia. Jeśli później pojawi się lepszy (tj. Węższy) indeks, to pozwoliłoby to na utworzenie nowego ograniczenia klucza obcego związanego z lepszym indeksem, a następnie pierwotne ograniczenie zostało usunięte bez żadnej przerwy bez aktywnego ograniczenia.

(Jak w przykładzie poniżej)

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;

Pomijając okres przejściowy, podczas gdy istnieją oba ograniczenia, wszystkie wstawki są sprawdzane pod kątem obu indeksów.

Martin Smith
źródło
Czy można zastosować transakcję, aby zapewnić tę samą aktualizację bez ograniczeń? Czy ta metoda bez transakcji może być lepsza z powodu mniejszego blokowania?
binki
13

Nie ma sensu mieć identycznych ograniczeń klucza obcego., Czyli w tych samych kolumnach i odwoływać się do tej samej tabeli i kolumn.

To tak, jakby mieć ten sam czek 2 lub więcej razy.

ypercubeᵀᴹ
źródło
-Nie zgadzam się. Może istnieć szansa, że ​​tabela podstawowa potrzebuje dwóch osobnych kontroli. Zobacz poniżej przykład nadawca i odbiorca są zupełnie inni - stackoverflow.com/questions/40400483/…
trex
@trex mówisz o czymś innym. Pytanie brzmi: „Chcę wiedzieć, jaki jest pożytek z posiadania wielu kluczy obcych zdefiniowanych w tej samej kolumnie i odwołania do tej samej kolumny w innej tabeli ”.
ypercubeᵀᴹ
@ ypercubeᵀᴹ - Rozumiem. Dzięki za wyjaśnienie
trex
6

Z tego samego powodu możesz utworzyć 50 indeksów w tej samej kolumnie, dodać drugi plik dziennika, ustawić maksymalną pamięć serwera na 20 MB ... większość ludzi nie zrobi tych rzeczy, ale mogą istnieć uzasadnione powody, aby je robić od czasu do czasu, więc nie ma korzyści w tworzeniu narzutów w silniku, aby dodać kontrole do rzeczy, które są po prostu niewłaściwe.

Aaron Bertrand
źródło
2

Brzmi jak niebiesko-zielona rzecz.

Kiedy zaczniesz zmieniać kolor z niebieskiego na zielony, musisz tymczasowo utworzyć dodatkowe kopie rzeczy.

Chcemy tymczasowo utworzyć dodatkowy klucz obcy CHECK WITH NOCHECKi ON UPDATE CASCADE ON DELETE SET NULL; działa to na zasadzie działającego klucza obcego, ale istniejące wiersze nie są sprawdzane podczas tworzenia klucza.

Później po wyczyszczeniu wszystkich wierszy, które powinny pasować, utworzymy nowy klucz obcy bez żadnych opcji poleceń (domyślnie jest CHECK WITH CHECKto, co zwykle chcesz) i upuszczamy tymczasowy klucz obcy.

Zauważ, że jeśli po prostu upuściłeś i odtworzyłeś klucz obcy, niektóre rzędy śmieci mogą się wślizgnąć.

Jozuego
źródło