sql >> Database >  >> RDS >> Sqlserver

Wat u moet weten MET NOCHECK bij het inschakelen van een CHECK-beperking in SQL Server

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!


  1. Help alstublieft met STRING_SPLIT verbeteringen

  2. Hoe snel waarden in tabel in SQL Server Management Studio bewerken?

  3. Procedure:trigger maken voor automatische update gewijzigde datum met SQL Server 2008

  4. Een externe sleutel toewijzen aan een aangepaste kolomnaam