Jeśli masz ograniczenie klucza obcego w SQL Server, które jest obecnie wyłączone, możesz użyć poniższego kodu, aby je ponownie włączyć.
Po włączeniu ograniczenia klucza obcego można określić, czy należy sprawdzić istniejące dane w tabeli. Dotyczy to również sytuacji, gdy włączysz opcję CHECK
ograniczenie.
Poniżej znajdują się przykłady kodu umożliwiające włączenie ograniczenia klucza obcego, przy jednoczesnym określeniu każdej z tych różnych opcji.
Przykład 1 – Włącz wiązanie za pomocą WITH CHECK
Jest to zalecana metoda (chyba że masz konkretny powód, aby jej nie używać).
Oto przykład włączenia ograniczenia klucza obcego o nazwie FK_Albums_Artists
:
ALTER TABLE Albums WITH CHECK CHECK CONSTRAINT FK_Albums_Artists;
Tutaj wyraźnie stwierdzam WITH CHECK
, który informuje SQL Server, aby sprawdził istniejące dane przed włączeniem ograniczenia. Jeśli jakiekolwiek dane naruszają ograniczenie, ograniczenie nie zostanie włączone i pojawi się błąd.
To dobrze, ponieważ wymusza integralność referencyjną.
Podczas tworzenia nowego ograniczenia klucza obcego jest to ustawienie domyślne. Jednak po włączeniu istniejącego ograniczenia (tak jak robimy to tutaj) nie ustawienie domyślne.
Przykład 2 – Włącz wiązanie za pomocą funkcji WITH NOCHECK
W tym przykładzie ograniczenie jest włączone bez sprawdzania istniejących danych:
ALTER TABLE Albums WITH NOCHECK CHECK CONSTRAINT FK_Albums_Artists;
Tutaj wyraźnie stwierdzam WITH NOCHECK
, który informuje SQL Server, aby nie sprawdzał istniejących danych. Oznacza to, że ograniczenie zostanie włączone, nawet jeśli tabela zawiera już dane, które naruszają ograniczenie.
Jest to ustawienie domyślne podczas włączania ograniczenia (ale nie podczas jego tworzenia).
Jednym z niewielu powodów (prawdopodobnie jedynym powodem), dla którego warto to wykorzystać, jest chęć przechowywania nieprawidłowych danych w bazie danych. Być może masz jednorazowy wyjątek, w którym musisz wprowadzić wiersz lub więcej nieprawidłowych danych, ale wszystkie przyszłe dane muszą być zgodne z ograniczeniem.
Jednak nadal istnieje ryzyko związane z robieniem tego. Oto, co Microsoft ma do powiedzenia na ten temat:
Nie zalecamy tego, z wyjątkiem rzadkich przypadków. Nowe ograniczenie jest oceniane we wszystkich późniejszych aktualizacjach danych. Wszelkie naruszenia ograniczeń, które są pomijane przez WITH NOCHECK
po dodaniu ograniczenia może spowodować niepowodzenie przyszłych aktualizacji, jeśli zaktualizują one wiersze z danymi, które nie są zgodne z ograniczeniem.
Więc używając WITH NOCHECK
może potencjalnie powodować problemy w przyszłości.
Przykład 3 – Włącz ograniczenie za pomocą opcji domyślnej
Oto przykład z użyciem domyślnej opcji:
ALTER TABLE Albums CHECK CONSTRAINT FK_Albums_Artists;
Ten przykład jest odpowiednikiem poprzedniego przykładu. Ponieważ nie określiłem, czy sprawdzać, czy nie, SQL Server zakłada, że chcę WITH NOCHECK
.
Pamiętaj więc, aby wyraźnie określić WITH CHECK
jeśli chcesz uniknąć problemów z integralnością referencyjną.
Korzystanie z WITH NOCHECK usuwa zaufanie
Po włączeniu ograniczenia za pomocą (domyślnie) WITH NOCHECK
, jedną z konsekwencji, o której należy pamiętać, jest to, że SQL Server nie będzie już ufał temu ograniczeniu. Oznacza to jako niezaufane. W rzeczywistości jest już oznaczony jako niezaufany po wyłączeniu ograniczenia.
SQL Server ma is_not_trusted
flaga, którą ustawia na 1
kiedy wyłączysz ograniczenie klucza obcego (co oznacza, że nie jest zaufane) i jedynym sposobem na ustawienie go na 0
(zaufane) jest określenie WITH CHECK
po ponownym włączeniu ograniczenia. Z drugiej strony, używając WITH NOCHECK
po prostu włącza to bez sprawdzania istniejących danych.
Używając WITH CHECK
, upewnij się, że ograniczenie sprawdza wszystkie istniejące dane przed jego włączeniem. Jedynym sposobem, w jaki można to włączyć, jest zgodność wszystkich istniejących danych z ograniczeniem. Po sprawdzeniu wszystkich istniejących danych, ograniczeniu można zaufać.
Przykład 4 – Sprawdź status zaufanych/wyłączonych
Możesz sprawdzić status zaufanego i wyłączonego, wysyłając zapytanie do sys.foreign_keys
widok systemu.
Tak:
SELECT name AS 'Constraint', is_disabled, is_not_trusted FROM sys.foreign_keys;
Wynik:
+-------------------+---------------+------------------+ | Constraint | is_disabled | is_not_trusted | |-------------------+---------------+------------------| | FK_Albums_Artists | 0 | 1 | | FK_Albums_Genres | 0 | 0 | +-------------------+---------------+------------------+
To mówi mi, że ograniczenie, które włączyłem w poprzednim przykładzie ( FK_Albums_Artists ) nie jest zaufany.
Dzieje się tak, ponieważ włączyłem go przy użyciu domyślnego ustawienia, którym jest WITH NOCHECK
.
Jeśli włączę go ponownie za pomocą WITH CHECK
, oto co się dzieje:
ALTER TABLE Albums WITH CHECK CHECK CONSTRAINT FK_Albums_Artists; SELECT name AS 'Constraint', is_disabled, is_not_trusted FROM sys.foreign_keys;
Wynik:
+-------------------+---------------+------------------+ | Constraint | is_disabled | is_not_trusted | |-------------------+---------------+------------------| | FK_Albums_Artists | 0 | 0 | | FK_Albums_Genres | 0 | 0 | +-------------------+---------------+------------------+
Na szczęście w tym przypadku nie miałem żadnych danych, które naruszyłyby ograniczenie, więc ograniczenie zostało pomyślnie włączone i przywrócono jego zaufanie.
Jeśli istnieją dane, które naruszają ograniczenie, zostanie wyświetlony błąd i będę zmuszony naprawić dane, zanim będę mógł przywrócić zaufanie do ograniczenia.