Als u zich ooit in de situatie bevindt waarin u een CHECK
. opnieuw moet inschakelen beperking die eerder is uitgeschakeld, moet u er zeker van zijn dat u weet wat u doet.
In het bijzonder moet u het verschil begrijpen tussen WITH NOCHECK
en WITH CHECK
argumenten.
Deze argumenten kunnen worden gebruikt op het moment dat u de beperking inschakelt. Ze specificeren of bestaande gegevens al dan niet worden gevalideerd tegen uw opnieuw ingeschakelde (of nieuw toegevoegde) CHECK
beperking. In principe heeft u de mogelijkheid om alle bestaande gegevens te controleren op eventuele overtredingen tegen de beperking. Als u niets opgeeft, zullen bestaande gegevens niet worden gecontroleerd. Daarom is het belangrijk om te begrijpen hoe het werkt.
Trouwens, deze argumenten zijn ook van toepassing op externe sleutelbeperkingen.
Zoals je zou verwachten, WITH CHECK
specificeert dat bestaande gegevens worden gevalideerd en WITH NOCHECK
geeft aan dat dit niet het geval is. De standaard is WITH NOCHECK
.
Als u WITH NOCHECK
. gebruikt , wordt de beperking gemarkeerd als niet-vertrouwd. In feite wordt het gemarkeerd als niet-vertrouwd wanneer u de beperking uitschakelt. Maar wanneer u het opnieuw inschakelt, blijft het niet vertrouwd, tenzij u WITH CHECK
gebruikt . Met andere woorden, als u de "betrouwbaarheid" opnieuw wilt bevestigen, moet u dit expliciet specificeren.
Met andere woorden:
- Als je
WITH NOCHECK
. gebruikt , blijft de beperking niet vertrouwd. - Als je
WITH CHECK
gebruikt het wordt vertrouwd, maar alleen als alle bestaande gegevens aan de beperking voldoen. Als bestaande gegevens de beperking schenden, wordt de beperking niet ingeschakeld en ontvangt u een foutmelding.
Als ik zeg 'alle bestaande gegevens', bedoel ik natuurlijk alleen gegevens waarop de beperking van toepassing is.
Er kunnen scenario's zijn waarin u opzettelijk een beperking hebt uitgeschakeld omdat u gegevens moest invoeren die de beperking schenden. In dergelijke gevallen, als de ongeldige gegevens in de database moeten blijven, moet u WITH NOCHECK
gebruiken als u de beperking opnieuw wilt inschakelen. Hierdoor kunt u de beperking inschakelen zonder dat bestaande gegevens in de weg zitten.
Hieronder staan voorbeelden die dit aantonen.
Voorbeeld 1 – Bekijk de beperkingen CONTROLEER
Laten we eerst de sys.check_constraints
. gebruiken om alle CHECK
te bekijken beperkingen in de huidige database.
SELECT name, is_disabled, is_not_trusted, definition FROM sys.check_constraints;
Resultaat:
+-----------------+---------------+------------------+----------------------------------------+ | name | is_disabled | is_not_trusted | definition | |-----------------+---------------+------------------+----------------------------------------| | chkPrice | 0 | 0 | ([Price]>(0)) | | chkValidEndDate | 0 | 0 | ([EndDate]>=[StartDate]) | | chkTeamSize | 0 | 0 | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | 0 | 0 | ([JobTitle]<>'Digital Nomad') | +-----------------+---------------+------------------+----------------------------------------+
We kunnen zien dat ze allemaal ingeschakeld en vertrouwd zijn (omdat ze allemaal nullen hebben in de is_disabled en is_not_trusted kolommen).
Voor dit artikel zal ik de chkJobTitle uitschakelen en opnieuw inschakelen beperking.
Voorbeeld 2 – De beperking uitschakelen
Hier schakel ik de chkJobTitle . uit beperking:
ALTER TABLE Occupation NOCHECK CONSTRAINT chkJobTitle;
Klaar.
Laten we nu alle beperkingen opnieuw bekijken:
SELECT name, is_disabled, is_not_trusted, definition FROM sys.check_constraints;
Resultaat:
+-----------------+---------------+------------------+----------------------------------------+ | name | is_disabled | is_not_trusted | definition | |-----------------+---------------+------------------+----------------------------------------| | chkPrice | 0 | 0 | ([Price]>(0)) | | chkValidEndDate | 0 | 0 | ([EndDate]>=[StartDate]) | | chkTeamSize | 0 | 0 | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | 1 | 1 | ([JobTitle]<>'Digital Nomad') | +-----------------+---------------+------------------+----------------------------------------+
We kunnen zien dat het is uitgeschakeld (omdat het is_disabled is) kolom is ingesteld op 1 ).
Je merkt misschien dat de
is_not_trusted
kolom is ook ingesteld op
1
. Dit geeft aan dat de CHECK
beperking is niet voor alle rijen geverifieerd door het systeem.
Zoals gezegd, een CHECK
beperking kan alleen worden vertrouwd als alle gegevens met succes aan de voorwaarden van de beperking hebben voldaan. Wanneer we een beperking uitschakelen, opent dit de mogelijkheid dat ongeldige gegevens de database binnenkomen. Daarom kunnen we er niet 100% zeker van zijn dat alle gegevens geldig zijn, vandaar dat de beperking wordt gemarkeerd als niet vertrouwd.
De manier om ervoor te zorgen dat de beperking weer wordt vertrouwd, is door deze opnieuw in te schakelen met de WITH CHECK
argument. Dit zorgt ervoor dat de beperking alle gegevens controleert voordat deze opnieuw wordt ingeschakeld. Als gegevens ongeldig zijn, kunnen ze niet opnieuw worden ingeschakeld. U moet de gegevens bijwerken zodat ze geldig zijn, of u moet de beperking opnieuw inschakelen met de WITH NOCHECK
argument in plaats daarvan (waardoor de beperking niet vertrouwd blijft).
Voorbeeld 3 – Schakel de beperking in met de standaardinstellingen (MET NOCHECK)
Laten we de beperking opnieuw inschakelen en de query opnieuw uitvoeren.
Om de beperking in te schakelen, ben ik lui en gebruik ik de standaardinstellingen:
ALTER TABLE Occupation CHECK CONSTRAINT chkJobTitle;
Controleer nu de wijziging:
SELECT name, is_disabled, is_not_trusted, definition FROM sys.check_constraints;
Resultaat:
+-----------------+---------------+------------------+----------------------------------------+ | name | is_disabled | is_not_trusted | definition | |-----------------+---------------+------------------+----------------------------------------| | chkPrice | 0 | 0 | ([Price]>(0)) | | chkValidEndDate | 0 | 0 | ([EndDate]>=[StartDate]) | | chkTeamSize | 0 | 0 | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | 0 | 1 | ([JobTitle]<>'Digital Nomad') | +-----------------+---------------+------------------+----------------------------------------+
Heb je gezien wat er net gebeurde? Hoewel ik de beperking opnieuw heb ingeschakeld, wordt deze nog steeds niet vertrouwd.
Dit komt omdat ik lui was (of misschien gewoon vergeetachtig) toen ik de beperking inschakelde. Toen ik de beperking inschakelde, vergat ik WITH CHECK
op te geven . De standaard is WITH NOCHECK
wat betekent dat bestaande gegevens niet worden gecontroleerd bij het opnieuw inschakelen van de beperking.
Dit is waarom je zeker moet weten wat je doet als je CHECK
inschakelt (en FOREIGN KEY
) beperkingen. Door lui te zijn en niet expliciet een potentieel belangrijke instelling te specificeren, geven we SQL Server toestemming om een oogje dicht te knijpen voor problemen met bestaande gegevens.
Als de hele reden dat u de beperking moest uitschakelen echter is om gegevens in te voegen die de beperking schenden, dan is de standaard WITH NOCHECK
is waarschijnlijk wat je wilt.
Trouwens, voor nieuwe beperkingen is de standaard WITH CHECK
.
Maar in mijn geval heb ik geen . toegevoegd of bijgewerkt gegevens na het uitschakelen van de beperking, dus als het voorheen betrouwbaar was, zou het nu nog steeds betrouwbaar moeten zijn.
Dus hoe kan ik mijn beperking weer vertrouwen?
Voorbeeld 4 – Schakel de beperking in met WITH CHECK
Als ik wil dat mijn beperking weer wordt vertrouwd, moet ik expliciet WITH CHECK
opgeven wanneer u het opnieuw inschakelt.
Laten we de beperking weer uitschakelen:
ALTER TABLE Occupation NOCHECK CONSTRAINT chkJobTitle;
Dus nu ben ik terug waar ik was voordat ik het opnieuw inschakelde.
Wat ik had moeten doen toen ik het opnieuw inschakelde, was dit:
ALTER TABLE Occupation WITH CHECK CHECK CONSTRAINT chkJobTitle;
Kijk nu nog eens naar de beperking:
SELECT name, is_disabled, is_not_trusted, definition FROM sys.check_constraints;
Resultaat:
+-----------------+---------------+------------------+----------------------------------------+ | name | is_disabled | is_not_trusted | definition | |-----------------+---------------+------------------+----------------------------------------| | chkPrice | 0 | 0 | ([Price]>(0)) | | chkValidEndDate | 0 | 0 | ([EndDate]>=[StartDate]) | | chkTeamSize | 0 | 0 | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | 0 | 0 | ([JobTitle]<>'Digital Nomad') | +-----------------+---------------+------------------+----------------------------------------+
Opluchting! Mijn beperking is weer betrouwbaar.
Voorbeeld 5 – Schakel de beperking CHECK met ongeldige gegevens in
Natuurlijk wordt mijn beperking alleen weer vertrouwd omdat ik geen ongeldige gegevens heb ingevoegd terwijl deze was uitgeschakeld. Als ik dit had gedaan, zou ik het niet kunnen inschakelen met WITH CHECK
, zoals hieronder wordt aangetoond.
Als ik het weer uitschakel:
ALTER TABLE Occupation NOCHECK CONSTRAINT chkJobTitle;
Voer nu ongeldige gegevens in (en retourneer de resultaten):
INSERT INTO Occupation VALUES ( 7, 'Digital Nomad' ); SELECT OccupationId, JobTitle FROM Occupation;
Resultaat:
+----------------+-----------------+ | OccupationId | JobTitle | |----------------+-----------------| | 1 | Engineer | | 2 | Accountant | | 3 | Cleaner | | 4 | Attorney | | 5 | Sales Executive | | 6 | Uber Driver | | 7 | Digital Nomad | +----------------+-----------------+
We hebben dus met succes ongeldige gegevens ingevoerd (laatste rij).
Dit is ongeldig omdat de beperkingsdefinitie als volgt gaat:([JobTitle]<>'Digital Nomad')
Dit betekent dat de
JobTitle
kolom mag niet de tekst Digital Nomad
bevatten .
Laten we nu proberen de CHECK
. opnieuw in te schakelen beperking met WITH CHECK
en kijk wat er gebeurt.
ALTER TABLE Occupation WITH CHECK CHECK CONSTRAINT chkJobTitle;
Resultaat:
Msg 547, Level 16, State 0, Line 1 The ALTER TABLE statement conflicted with the CHECK constraint "chkJobTitle". The conflict occurred in database "Test", table "dbo.Occupation", column 'JobTitle'.
We kunnen de beperking dus niet opnieuw inschakelen met WITH CHECK
terwijl we gegevens in de tabel hebben die in strijd zijn met de CHECK
beperking. Ofwel moeten we de gegevens bijwerken of we moeten WITH NOCHECK
. gebruiken (of gewoon helemaal weglaten).
Laten we het opnieuw proberen met WITH NOCHECK
.
ALTER TABLE Occupation WITH NOCHECK CHECK CONSTRAINT chkJobTitle;
Resultaat:
Commands completed successfully. Total execution time: 00:00:00.015
We kunnen de beperking dus met succes inschakelen als we de bestaande gegevens niet controleren.
Natuurlijk, in dit geval de CHECK
beperking is nog steeds niet vertrouwd. Als we willen dat de beperking wordt vertrouwd, moeten we de gegevens bijwerken zodat deze de beperking niet schenden.
Voorbeeld:
UPDATE Occupation SET JobTitle = 'Unemployed' WHERE OccupationId = 7; SELECT OccupationId, JobTitle FROM Occupation;
Resultaat:
+----------------+-----------------+ | OccupationId | JobTitle | |----------------+-----------------| | 1 | Engineer | | 2 | Accountant | | 3 | Cleaner | | 4 | Attorney | | 5 | Sales Executive | | 6 | Uber Driver | | 7 | Unemployed | +----------------+-----------------+
Nu kunnen we de CHECK
. wijzigen beperking om weer vertrouwd te worden.
Laten we ze alle drie samen doen:
ALTER TABLE Occupation NOCHECK CONSTRAINT chkJobTitle; ALTER TABLE Occupation WITH CHECK CHECK CONSTRAINT chkJobTitle; SELECT name, is_disabled, is_not_trusted, definition FROM sys.check_constraints;
Resultaat:
+-----------------+---------------+------------------+----------------------------------------+ | name | is_disabled | is_not_trusted | definition | |-----------------+---------------+------------------+----------------------------------------| | chkPrice | 0 | 0 | ([Price]>(0)) | | chkValidEndDate | 0 | 0 | ([EndDate]>=[StartDate]) | | chkTeamSize | 0 | 0 | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | 0 | 0 | ([JobTitle]<>'Digital Nomad') | +-----------------+---------------+------------------+----------------------------------------+
Dus nu is onze beperking weer ingeschakeld en betrouwbaar, en onze database is vrij van digitale nomaden!