Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Was Sie über WITH NOCHECK wissen sollten, wenn Sie eine CHECK-Einschränkung in SQL Server aktivieren

Wenn Sie sich jemals in der Situation befinden, in der Sie einen CHECK erneut aktivieren müssen Einschränkung, die zuvor deaktiviert wurde, sollten Sie auf jeden Fall sicherstellen, dass Sie wissen, was Sie tun.

Insbesondere sollten Sie den Unterschied zwischen WITH NOCHECK verstehen und WITH CHECK Argumente.

Diese Argumente können verwendet werden, wenn Sie die Einschränkung aktivieren. Sie geben an, ob vorhandene Daten gegen Ihren wieder aktivierten (oder neu hinzugefügten) CHECK validiert werden oder nicht Zwang. Grundsätzlich haben Sie die Möglichkeit, alle vorhandenen Daten auf Verstöße gegen die Beschränkung zu prüfen. Wenn Sie nichts angeben, werden vorhandene Daten nicht überprüft werden. Deshalb ist es wichtig zu verstehen, wie es funktioniert.

Übrigens gelten diese Argumente auch für Foreign Key Constraints.

Wie zu erwarten, WITH CHECK gibt an, dass vorhandene Daten validiert werden und WITH NOCHECK gibt an, dass dies nicht der Fall ist. Der Standardwert ist WITH NOCHECK .

Wenn Sie WITH NOCHECK verwenden , wird die Einschränkung als nicht vertrauenswürdig gekennzeichnet. Tatsächlich wird es als nicht vertrauenswürdig gekennzeichnet, wenn Sie die Einschränkung deaktivieren. Aber wenn Sie es wieder aktivieren, bleibt es nicht vertrauenswürdig, es sei denn, Sie verwenden WITH CHECK . Mit anderen Worten, wenn Sie seine „Vertrauenswürdigkeit“ bekräftigen möchten, müssen Sie dies ausdrücklich angeben.

Mit anderen Worten:

  • Wenn Sie WITH NOCHECK verwenden , bleibt die Einschränkung nicht vertrauenswürdig.
  • Wenn Sie WITH CHECK verwenden es wird vertrauenswürdig, aber nur, wenn alle vorhandenen Daten der Einschränkung entsprechen. Wenn vorhandene Daten gegen die Einschränkung verstoßen, wird die Einschränkung nicht aktiviert und Sie erhalten eine Fehlermeldung.

Wenn ich „alle vorhandenen Daten“ sage, beziehe ich mich natürlich nur auf Daten, für die die Einschränkung gilt.

Es kann Szenarien geben, in denen Sie eine Einschränkung absichtlich deaktiviert haben, weil Sie Daten eingeben mussten, die gegen die Einschränkung verstoßen. Wenn in solchen Fällen die ungültigen Daten in der Datenbank verbleiben müssen, müssen Sie WITH NOCHECK verwenden wenn Sie die Einschränkung wieder aktivieren möchten. Auf diese Weise können Sie die Einschränkung aktivieren, ohne dass vorhandene Daten im Weg stehen.

Nachfolgend finden Sie Beispiele, die dies demonstrieren.

Beispiel 1 – Überprüfen Sie die CHECK-Einschränkungen

Lassen Sie uns zuerst die sys.check_constraints verwenden um einen Blick auf alle CHECK zu werfen Beschränkungen in der aktuellen Datenbank.

SELECT name, is_disabled, is_not_trusted, definitionFROM sys.check_constraints;

Ergebnis:

+------------+---------------+------------ ------+----------------------------------------+| Name | ist_deaktiviert | is_not_trusted | Definition ||-----------------+---------------+--------------------- -----+----------------------------------------|| chkPreis | 0 | 0 | ([Preis]>(0)) || chkValidEndDate | 0 | 0 | ([Enddatum]>=[Startdatum]) || chkTeamSize | 0 | 0 | ([Teamgröße]>=(5) UND [Teamgröße]<=(20)) || chkJobTitel | 0 | 0 | ([JobTitle]<>'Digitaler Nomade') |+-----------------+---------------+--- -------------------------------------------------- ------+

Wir können sehen, dass sie alle aktiviert und vertrauenswürdig sind (weil sie alle Nullen in is_disabled haben und is_not_trusted Spalten).

Für diesen Artikel werde ich chkJobTitle deaktivieren und wieder aktivieren Einschränkung.

Beispiel 2 – Einschränkung deaktivieren

Hier deaktiviere ich den chkJobTitle Einschränkung:

ALTER TABLE Beruf NOCHECK CONSTRAINT chkJobTitle; 

Fertig.

Sehen wir uns nun noch einmal alle Beschränkungen an:

SELECT name, is_disabled, is_not_trusted, definitionFROM sys.check_constraints;

Ergebnis:

+------------+---------------+------------ ------+----------------------------------------+| Name | ist_deaktiviert | is_not_trusted | Definition ||-----------------+---------------+--------------------- -----+----------------------------------------|| chkPreis | 0 | 0 | ([Preis]>(0)) || chkValidEndDate | 0 | 0 | ([Enddatum]>=[Startdatum]) || chkTeamSize | 0 | 0 | ([Teamgröße]>=(5) UND [Teamgröße]<=(20)) || chkJobTitel | 1 | 1 | ([JobTitle]<>'Digitaler Nomade') |+-----------------+---------------+--- -------------------------------------------------- ------+

Wir können sehen, dass es deaktiviert wurde (weil seine is_disabled Spalte ist auf 1 gesetzt ).

Möglicherweise stellen Sie fest, dass is_not_trusted ist Spalte wird ebenfalls auf 1 gesetzt . Dies zeigt an, dass der CHECK Einschränkung wurde vom System nicht für alle Zeilen verifiziert.

Wie gesagt, ein CHECK Einschränkung kann nur vertraut werden, wenn alle Daten die Bedingungen der Einschränkung erfolgreich bestanden haben. Wenn wir eine Einschränkung deaktivieren, eröffnet dies die Möglichkeit, dass ungültige Daten in die Datenbank gelangen. Daher können wir nicht 100 % sicher sein, dass alle Daten gültig sind, daher wird die Einschränkung als nicht vertrauenswürdig gekennzeichnet.

Um sicherzustellen, dass der Einschränkung wieder vertraut wird, müssen Sie sie mit WITH CHECK erneut aktivieren Streit. Dadurch überprüft die Einschränkung alle Daten, bevor sie wieder aktiviert wird. Wenn Daten ungültig sind, können sie nicht wieder aktiviert werden. Sie müssen entweder die Daten aktualisieren, damit sie gültig sind, oder die Einschränkung mit WITH NOCHECK erneut aktivieren Argument (was dazu führt, dass die Einschränkung nicht vertrauenswürdig bleibt).

Beispiel 3 – Aktivieren Sie die Einschränkung mit den Standardeinstellungen (MIT NOCHECK)

Lassen Sie uns die Einschränkung wieder aktivieren und die Abfrage erneut ausführen.

Um die Einschränkung zu aktivieren, bin ich faul und verwende die Standardeinstellungen:

ALTER TABLE Beruf CHECK CONSTRAINT chkJobTitle; 

Überprüfen Sie nun die Änderung:

SELECT name, is_disabled, is_not_trusted, definitionFROM sys.check_constraints;

Ergebnis:

+------------+---------------+------------ ------+----------------------------------------+| Name | ist_deaktiviert | is_not_trusted | Definition ||-----------------+---------------+--------------------- -----+----------------------------------------|| chkPreis | 0 | 0 | ([Preis]>(0)) || chkValidEndDate | 0 | 0 | ([Enddatum]>=[Startdatum]) || chkTeamSize | 0 | 0 | ([Teamgröße]>=(5) UND [Teamgröße]<=(20)) || chkJobTitel | 0 | 1 | ([JobTitle]<>'Digitaler Nomade') |+-----------------+---------------+--- -------------------------------------------------- ------+

Hast du gesehen, was gerade passiert ist? Obwohl ich die Einschränkung erneut aktiviert habe, wird ihr immer noch nicht vertraut.

Das liegt daran, dass ich faul (oder vielleicht einfach nur vergesslich) war, als ich die Einschränkung aktivierte. Als ich die Einschränkung aktiviert habe, habe ich vergessen, WITH CHECK anzugeben . Der Standardwert ist WITH NOCHECK Das bedeutet, dass vorhandene Daten nicht überprüft werden, wenn die Einschränkung erneut aktiviert wird.

Deshalb sollten Sie unbedingt wissen, was Sie tun, wenn Sie CHECK aktivieren (und FOREIGN KEY ) Einschränkungen. Indem wir faul sind und eine potenziell wichtige Einstellung nicht explizit angeben, geben wir SQL Server die Erlaubnis, Probleme mit vorhandenen Daten zu ignorieren.

Wenn der einzige Grund, warum Sie die Einschränkung deaktivieren mussten, darin besteht, Daten einzufügen, die gegen die Einschränkung verstoßen, dann ist die Voreinstellung WITH NOCHECK ist wahrscheinlich das, was Sie wollen.

Übrigens, für neue Constraints ist die Voreinstellung WITH CHECK .

Aber in meinem Fall habe ich keine eingefügt oder aktualisiert Daten nach dem Deaktivieren der Einschränkung. Wenn sie also vorher vertrauenswürdig waren, sollten sie jetzt immer noch vertrauenswürdig sein.

Wie kann ich also dafür sorgen, dass meiner Einschränkung wieder vertraut wird?

Beispiel 4 – Aktivieren Sie die Einschränkung mit WITH CHECK

Wenn ich möchte, dass meiner Einschränkung wieder vertraut wird, muss ich explizit WITH CHECK angeben bei der erneuten Aktivierung.

Lassen Sie uns die Einschränkung wieder deaktivieren:

ALTER TABLE Beruf NOCHECK CONSTRAINT chkJobTitle; 

Jetzt bin ich also wieder dort, wo ich war, bevor ich es wieder aktiviert habe.

Was ich hätte tun sollen, als ich es wieder aktiviert habe, war Folgendes:

ALTER TABLE Beruf WITH CHECK CHECK CONSTRAINT chkJobTitle; 

Sehen Sie sich nun die Einschränkung noch einmal an:

SELECT name, is_disabled, is_not_trusted, definitionFROM sys.check_constraints;

Ergebnis:

+------------+---------------+------------ ------+----------------------------------------+| Name | ist_deaktiviert | is_not_trusted | Definition ||-----------------+---------------+--------------------- -----+----------------------------------------|| chkPreis | 0 | 0 | ([Preis]>(0)) || chkValidEndDate | 0 | 0 | ([Enddatum]>=[Startdatum]) || chkTeamSize | 0 | 0 | ([Teamgröße]>=(5) UND [Teamgröße]<=(20)) || chkJobtitel | 0 | 0 | ([JobTitle]<>'Digitaler Nomade') |+-----------------+---------------+--- -------------------------------------------------- ------+

Puh! Mein Zwang ist wieder vertrauenswürdig.

Beispiel 5 – Aktivieren Sie die CHECK-Einschränkung mit ungültigen Daten

Natürlich wird meiner Einschränkung nur wieder vertraut, weil ich keine ungültigen Daten eingefügt habe, während sie deaktiviert war. Wenn ich das getan hätte, könnte ich es nicht mit WITH CHECK aktivieren , wie unten gezeigt.

Wenn ich es wieder deaktiviere:

ALTER TABLE Beruf NOCHECK CONSTRAINT chkJobTitle; 

Fügen Sie nun ungültige Daten ein (und geben Sie die Ergebnisse zurück):

INSERT INTO OccupationVALUES ( 7, 'Digital Nomad' );SELECT OccupationId, JobTitleFROM Occupation;

Ergebnis:

+----------------+----------------+| BerufsID | Berufsbezeichnung ||----------------+-----------------|| 1 | Ingenieur || 2 | Buchhalter || 3 | Reiniger || 4 | Rechtsanwalt || 5 | Verkaufsleiter || 6 | Uber-Fahrer || 7 | Digitaler Nomade |+----------------+----------------+

Wir haben also erfolgreich ungültige Daten eingefügt (letzte Zeile).

Dies ist ungültig, da die Einschränkungsdefinition wie folgt lautet:([JobTitle]<>'Digital Nomad')

Das bedeutet, dass der JobTitle Spalte darf nicht den Text Digital Nomad enthalten .

Versuchen wir nun, den CHECK wieder zu aktivieren Einschränkung mit WITH CHECK und sehen, was passiert.

ALTER TABLE Beruf WITH CHECK CHECK CONSTRAINT chkJobTitle; 

Ergebnis:

Msg 547, Ebene 16, Status 0, Zeile 1 Die ALTER TABLE-Anweisung stand in Konflikt mit der CHECK-Einschränkung „chkJobTitle“. Der Konflikt ist in Datenbank „Test“, Tabelle „dbo.Occupation“, Spalte „JobTitle“ aufgetreten.

Wir können die Einschränkung also nicht mit WITH CHECK wieder aktivieren während wir Daten in der Tabelle haben, die den CHECK verletzen Zwang. Entweder müssen wir die Daten aktualisieren oder wir müssen WITH NOCHECK verwenden (oder einfach ganz weglassen).

Versuchen wir es noch einmal mit WITH NOCHECK .

ALTER TABLE Beruf WITH NOCHECK CHECK CONSTRAINT chkJobTitle; 

Ergebnis:

Befehle erfolgreich abgeschlossen. Gesamtausführungszeit:00:00:00.015

So können wir die Einschränkung erfolgreich aktivieren, wenn wir die vorhandenen Daten nicht überprüfen.

In diesem Fall natürlich der CHECK Constraint wird immer noch nicht vertraut. Wenn wir möchten, dass der Einschränkung vertraut wird, müssen wir die Daten aktualisieren, damit sie nicht gegen die Einschränkung verstoßen.

Beispiel:

UPDATE OccupationSET JobTitle ='Arbeitslos'WHERE OccupationId =7;SELECT OccupationId, JobTitleFROM Occupation;

Ergebnis:

+----------------+----------------+| BerufsID | Berufsbezeichnung ||----------------+-----------------|| 1 | Ingenieur || 2 | Buchhalter || 3 | Reiniger || 4 | Rechtsanwalt || 5 | Verkaufsleiter || 6 | Uber-Fahrer || 7 | Arbeitslos |+----------------+----------------+

Jetzt können wir den CHECK ändern Einschränkung, wieder vertrauenswürdig zu werden.

Lassen Sie uns alle drei zusammen machen:

ALTER TABLE Beruf NOCHECK CONSTRAINT chkJobTitle; ALTER TABLE Beruf WITH CHECK CHECK CONSTRAINT chkJobTitle; SELECT name, is_disabled, is_not_trusted, definitionFROM sys.check_constraints;

Ergebnis:

+------------+---------------+------------ ------+----------------------------------------+| Name | ist_deaktiviert | is_not_trusted | Definition ||-----------------+---------------+--------------------- -----+----------------------------------------|| chkPreis | 0 | 0 | ([Preis]>(0)) || chkValidEndDate | 0 | 0 | ([Enddatum]>=[Startdatum]) || chkTeamSize | 0 | 0 | ([Teamgröße]>=(5) UND [Teamgröße]<=(20)) || chkJobtitel | 0 | 0 | ([JobTitle]<>'Digitaler Nomade') |+-----------------+---------------+--- -------------------------------------------------- ------+

Jetzt ist unsere Einschränkung also wieder aktiviert und vertrauenswürdig, und unsere Datenbank ist frei von digitalen Nomaden!