Pokud máte na serveru SQL Server omezení cizího klíče, které je aktuálně zakázáno, můžete jej znovu povolit pomocí kódu níže.
Když povolíte omezení cizího klíče, máte možnost určit, zda chcete nebo nechcete kontrolovat jakákoli existující data v tabulce. To platí také, když povolíte CHECK
omezení.
Níže jsou uvedeny příklady kódu pro povolení omezení cizího klíče při specifikaci každé z těchto různých možností.
Příklad 1 – Povolte omezení pomocí WITH CHECK
Toto je doporučená metoda (pokud nemáte konkrétní důvod ji nepoužívat).
Zde je příklad povolení omezení cizího klíče s názvem FK_Albums_Artists
:
ALTER TABLE Albums WITH CHECK CHECK CONSTRAINT FK_Albums_Artists;
Zde výslovně uvádím WITH CHECK
, který říká serveru SQL Server, aby zkontroloval existující data před povolením omezení. Pokud některá data porušují omezení, omezení nebude povoleno a zobrazí se chyba.
To je dobré, protože to vynucuje referenční integritu.
Když vytvoříte nové omezení cizího klíče, jedná se o výchozí nastavení. Když však povolíte existující omezení (jak to děláme zde), není výchozí nastavení.
Příklad 2 – Povolte omezení pomocí WITH NOCHECK
V tomto příkladu je omezení povoleno bez kontroly existujících dat:
ALTER TABLE Albums WITH NOCHECK CHECK CONSTRAINT FK_Albums_Artists;
Zde výslovně uvádím WITH NOCHECK
, který říká SQL Serveru, aby nekontroloval existující data. To znamená, že omezení bude povoleno, i když tabulka již obsahuje data, která omezení porušují.
Toto je výchozí nastavení při povolení omezení (ale ne při vytváření omezení).
Jeden z mála důvodů (pravděpodobně jediný důvod), proč byste to použili, je, pokud chcete v databázi ponechat neplatná data. Možná máte jednorázovou výjimku, kdy musíte zadat řádek nebo více neplatných dat, ale požadujete, aby všechna budoucí data odpovídala omezení.
Stále však existují rizika spojená s tím. Zde je to, co k tomu říká společnost Microsoft:
Nedoporučujeme to dělat, s výjimkou vzácných případů. Nové omezení je vyhodnoceno ve všech pozdějších aktualizacích dat. Jakákoli porušení omezení, která jsou potlačena pomocí
WITH NOCHECK
Když je omezení přidáno, může to způsobit selhání budoucích aktualizací, pokud aktualizují řádky daty, která omezení nedodržují.
Takže pomocí WITH NOCHECK
může později způsobit problémy.
Příklad 3 – Povolení omezení pomocí výchozí možnosti
Zde je příklad použití výchozí možnosti:
ALTER TABLE Albums CHECK CONSTRAINT FK_Albums_Artists;
Tento příklad je ekvivalentem předchozího příkladu. Protože jsem nespecifikoval, zda zkontrolovat nebo ne, SQL Server předpokládá, že chci WITH NOCHECK
.
Ujistěte se tedy, že jste výslovně uvedli WITH CHECK
pokud se chcete vyhnout problémům s referenční integritou.
Použití WITH NOCHECK odstraňuje důvěru
Když povolíte omezení pomocí (výchozí) WITH NOCHECK
Jedním z důsledků, o kterém byste si měli být vědomi, je, že SQL Server již nebude tomuto omezení důvěřovat. Označí to jako nedůvěryhodné. Ve skutečnosti je již označen jako nedůvěryhodný, když omezení deaktivujete.
SQL Server má is_not_trusted
příznak, který nastaví na 1
když zakážete omezení cizího klíče (což znamená, že není důvěryhodné), a jediný způsob, jak jej nastavit na 0
(důvěryhodný) je zadat WITH CHECK
při opětovném povolení omezení. Na druhou stranu pomocí WITH NOCHECK
pouze to povolí bez kontroly existujících dat.
Pomocí WITH CHECK
, zajistíte, že omezení zkontroluje všechna existující data, než bude povoleno. Jediným způsobem, jak jej lze povolit, je, že všechna existující data vyhovují omezení. Jakmile zkontroluje všechna existující data, může být omezení důvěryhodné.
Příklad 4 – Kontrola stavu Důvěryhodný/Zakázán
Stav důvěryhodnosti a deaktivace můžete zkontrolovat dotazem na sys.foreign_keys
systémový pohled.
Takhle:
SELECT name AS 'Constraint', is_disabled, is_not_trusted FROM sys.foreign_keys;
Výsledek:
+-------------------+---------------+------------------+ | Constraint | is_disabled | is_not_trusted | |-------------------+---------------+------------------| | FK_Albums_Artists | 0 | 1 | | FK_Albums_Genres | 0 | 0 | +-------------------+---------------+------------------+
To mi říká, že omezení, které jsem povolil v předchozím příkladu ( FK_Albums_Artists ) není důvěryhodný.
Je to proto, že jsem to povolil pomocí výchozího nastavení, které je WITH NOCHECK
.
Pokud jej znovu povolím pomocí WITH CHECK
, stane se toto:
ALTER TABLE Albums WITH CHECK CHECK CONSTRAINT FK_Albums_Artists; SELECT name AS 'Constraint', is_disabled, is_not_trusted FROM sys.foreign_keys;
Výsledek:
+-------------------+---------------+------------------+ | Constraint | is_disabled | is_not_trusted | |-------------------+---------------+------------------| | FK_Albums_Artists | 0 | 0 | | FK_Albums_Genres | 0 | 0 | +-------------------+---------------+------------------+
Naštěstí v tomto případě jsem neměl žádná data, která by porušovala omezení, takže omezení bylo úspěšně povoleno a jeho důvěryhodnost byla obnovena.
Pokud by existovala data, která porušovala omezení, zobrazila by se chyba a byl bych nucen data opravit, než budu moci obnovit důvěru v omezení.