sql >> Database teknologi >  >> RDS >> Sqlserver

Hvad du bør vide om MED NOCHECK, når du aktiverer en CHECK-begrænsning i SQL Server

Hvis du nogensinde kommer i den situation, hvor du skal genaktivere en CHECK begrænsning, der tidligere er blevet deaktiveret, bør du helt sikkert sikre dig, at du ved, hvad du laver.

Især bør du forstå forskellen mellem WITH NOCHECK og WITH CHECK argumenter.

Disse argumenter kan bruges på det tidspunkt, du aktiverer begrænsningen. De angiver, om eksisterende data er valideret mod din genaktiverede (eller nyligt tilføjede) CHECK begrænsning. Som udgangspunkt har du mulighed for at kontrollere alle eksisterende data for eventuelle overtrædelser af begrænsningen. Hvis du ikke angiver noget, vil eksisterende data ikke blive kontrolleret. Derfor er det vigtigt at forstå, hvordan det fungerer.

Disse argumenter gælder forresten også for fremmednøglebegrænsninger.

Som du måske forventer, WITH CHECK angiver, at eksisterende data er valideret og WITH NOCHECK angiver, at det ikke er det. Standardindstillingen er WITH NOCHECK .

Hvis du bruger WITH NOCHECK , vil begrænsningen blive markeret som upålidelig. Faktisk er den markeret som upålidelig, når du deaktiverer begrænsningen. Men når du genaktiverer den, vil den forblive upålidelig, medmindre du bruger WITH CHECK . Med andre ord, hvis du vil gentage dens "troværdighed", skal du udtrykkeligt angive dette.

Med andre ord:

  • Når du bruger WITH NOCHECK , vil begrænsningen forblive upålidelig.
  • Når du bruger WITH CHECK det vil blive betroet, men kun hvis alle eksisterende data er i overensstemmelse med begrænsningen. Hvis eksisterende data overtræder begrænsningen, vil begrænsningen ikke blive aktiveret, og du vil modtage en fejlmeddelelse.

Når jeg siger "alle eksisterende data", henviser jeg selvfølgelig kun til data, som begrænsningen gælder for.

Der kan være scenarier, hvor du med vilje har deaktiveret en begrænsning, fordi du skulle indtaste data, der overtræder begrænsningen. I sådanne tilfælde, hvis de ugyldige data skal forblive i databasen, skal du bruge WITH NOCHECK hvis du vil genaktivere begrænsningen. Dette vil give dig mulighed for at aktivere begrænsningen uden at eksisterende data kommer i vejen.

Nedenfor er eksempler, der demonstrerer dette.

Eksempel 1 – Gennemgå begrænsninger for tjek

Lad os først bruge sys.check_constraints for at tage et kig på alle CHECK begrænsninger i den aktuelle database.

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Resultat:

+-----------------+---------------+------------------+----------------------------------------+
| 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')          |
+-----------------+---------------+------------------+----------------------------------------+

Vi kan se, at de alle er aktiveret og har tillid til (fordi de alle har nuller i is_disabled og is_not_trusted kolonner).

For denne artikel vil jeg deaktivere og genaktivere chkJobTitle begrænsning.

Eksempel 2 – Deaktiver begrænsningen

Her deaktiverer jeg chkJobTitle begrænsning:

ALTER TABLE Occupation  
NOCHECK CONSTRAINT chkJobTitle; 

Færdig.

Lad os nu gennemgå alle begrænsninger igen:

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Resultat:

+-----------------+---------------+------------------+----------------------------------------+
| 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')          |
+-----------------+---------------+------------------+----------------------------------------+

Vi kan se, at det er blevet deaktiveret (fordi det is_disabled kolonne er indstillet til 1 ).

Du bemærker måske, at is_not_trusted kolonne er også indstillet til 1 . Dette indikerer, at CHECK begrænsning er ikke blevet bekræftet af systemet for alle rækker.

Som nævnt en CHECK begrænsning kan kun stoles på, hvis alle data har bestået begrænsningens betingelser. Når vi deaktiverer en begrænsning, åbner dette muligheden for, at ugyldige data kommer ind i databasen. Derfor kan vi ikke være 100 % sikre på, at alle data er gyldige, og derfor er begrænsningen markeret som ikke-pålidelig.

Måden at sikre, at begrænsningen er tillid til igen, er at genaktivere den ved hjælp af WITH CHECK argument. Dette vil få begrænsningen til at kontrollere alle data, før den genaktiveres. Hvis nogen data er ugyldige, vil de ikke kunne genaktiveres. Du skal enten opdatere dataene, så de er gyldige, eller genaktivere begrænsningen ved hjælp af WITH NOCHECK argument i stedet (hvilket vil få begrænsningen til at forblive upålidelig).

Eksempel 3 – Aktiver begrænsningen ved hjælp af standardindstillingerne (MED NØK)

Lad os genaktivere begrænsningen og køre forespørgslen igen.

For at aktivere begrænsningen vil jeg være doven og bruge standardindstillingerne:

ALTER TABLE Occupation  
CHECK CONSTRAINT chkJobTitle; 

Bekræft nu ændringen:

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Resultat:

+-----------------+---------------+------------------+----------------------------------------+
| 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')          |
+-----------------+---------------+------------------+----------------------------------------+

Så du, hvad der lige skete? Selvom jeg aktiverede begrænsningen igen, er der stadig ingen tillid til den.

Dette skyldes, at jeg var doven (eller måske bare glemsom), da jeg aktiverede begrænsningen. Da jeg aktiverede begrænsningen, glemte jeg at angive WITH CHECK . Standardindstillingen er WITH NOCHECK hvilket betyder, at eksisterende data ikke kontrolleres, når begrænsningen genaktiveres.

Det er derfor, du helt sikkert bør vide, hvad du gør, når du aktiverer CHECK (og FOREIGN KEY ) begrænsninger. Ved at være doven og ikke eksplicit angive en potentielt vigtig indstilling, giver vi SQL Server tilladelse til at vende det blinde øje til eventuelle problemer med eksisterende data.

Men hvis hele grunden til at du skulle deaktivere begrænsningen er at indsætte data, der overtræder begrænsningen, så er standarden WITH NOCHECK er sandsynligvis, hvad du ønsker.

For nye begrænsninger er standarden WITH CHECK .

Men i mit tilfælde har jeg ikke indsat eller opdateret nogle data efter deaktivering af begrænsningen, så hvis det var troværdigt før, skulle det stadig være troværdigt nu.

Så hvordan kan jeg få tillid til min begrænsning igen?

Eksempel 4 – Aktiver begrænsningen ved hjælp af MED KONTROL

Hvis jeg vil have tillid til min begrænsning igen, skal jeg udtrykkeligt angive WITH CHECK når du genaktiverer det.

Lad os deaktivere begrænsningen igen:

ALTER TABLE Occupation  
NOCHECK CONSTRAINT chkJobTitle; 

Så nu er jeg tilbage til, hvor jeg var, før jeg genaktiverede det.

Hvad jeg skulle have gjort, da jeg genaktiverede det, var dette:

ALTER TABLE Occupation  
WITH CHECK CHECK CONSTRAINT chkJobTitle; 

Tag nu endnu et kig på begrænsningen:

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Resultat:

+-----------------+---------------+------------------+----------------------------------------+
| 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')          |
+-----------------+---------------+------------------+----------------------------------------+

Pyha! Min begrænsning er troværdig igen.

Eksempel 5 – Aktiver CHECK-begrænsningen med ugyldige data

Selvfølgelig er min begrænsning kun tillid til igen, fordi jeg ikke indsatte ugyldige data, mens den var deaktiveret. Hvis jeg havde gjort dette, ville jeg ikke være i stand til at aktivere det ved hjælp af WITH CHECK , som vist nedenfor.

Hvis jeg deaktiverer det igen:

ALTER TABLE Occupation  
NOCHECK CONSTRAINT chkJobTitle; 

Indsæt nu ugyldige data (og returner resultaterne):

INSERT INTO Occupation
VALUES ( 7, 'Digital Nomad' );

SELECT 
  OccupationId,
  JobTitle
FROM Occupation;

Resultat:

+----------------+-----------------+
| OccupationId   | JobTitle        |
|----------------+-----------------|
| 1              | Engineer        |
| 2              | Accountant      |
| 3              | Cleaner         |
| 4              | Attorney        |
| 5              | Sales Executive |
| 6              | Uber Driver     |
| 7              | Digital Nomad   |
+----------------+-----------------+

Så vi har indsat ugyldige data (sidste række).

Dette er ugyldigt, fordi begrænsningsdefinitionen er som følger:([JobTitle]<>'Digital Nomad')

Det betyder, at JobTitle kolonne må ikke indeholde teksten Digital Nomad .

Lad os nu prøve at genaktivere CHECK begrænsning ved hjælp af WITH CHECK og se, hvad der sker.

ALTER TABLE Occupation  
WITH CHECK CHECK CONSTRAINT chkJobTitle; 

Resultat:

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'.

Så vi kan ikke genaktivere begrænsningen ved hjælp af WITH CHECK mens vi har data i tabellen, der overtræder CHECK begrænsning. Enten skal vi opdatere dataene, eller også skal vi bruge WITH NOCHECK (eller bare udelad det helt).

Lad os prøve det igen ved at bruge WITH NOCHECK .

ALTER TABLE Occupation  
WITH NOCHECK CHECK CONSTRAINT chkJobTitle; 

Resultat:

Commands completed successfully.
Total execution time: 00:00:00.015

Så vi kan med succes aktivere begrænsningen, hvis vi ikke tjekker de eksisterende data.

Selvfølgelig, i dette tilfælde CHECK begrænsning er stadig ikke tillid til. Hvis vi vil have tillid til begrænsningen, skal vi opdatere dataene, så de ikke overtræder begrænsningen.

Eksempel:

UPDATE Occupation
SET JobTitle = 'Unemployed'
WHERE OccupationId = 7;

SELECT 
  OccupationId,
  JobTitle
FROM Occupation;

Resultat:

+----------------+-----------------+
| OccupationId   | JobTitle        |
|----------------+-----------------|
| 1              | Engineer        |
| 2              | Accountant      |
| 3              | Cleaner         |
| 4              | Attorney        |
| 5              | Sales Executive |
| 6              | Uber Driver     |
| 7              | Unemployed      |
+----------------+-----------------+

Nu kan vi ændre CHECK begrænsning for at blive betroet igen.

Lad os gøre alle tre sammen:

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;

Resultat:

+-----------------+---------------+------------------+----------------------------------------+
| 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')          |
+-----------------+---------------+------------------+----------------------------------------+

Så nu er vores begrænsning aktiveret og troværdig igen, og vores database er fri for digitale nomader!


  1. Befolkning af træelement med rekordgruppe i Oracle-formularer

  2. Brug MySQL relationelle databaser på Ubuntu 9.04 (Jaunty)

  3. Hvordan får man tabeldefinition i Oracle?

  4. Hvad er MySQL-ækvivalenten til SQL Servers CHOOSE()-funktion?