I SQL Server kan du oprette en CHECK
begrænsning i en tabel for at angive de dataværdier, der er acceptable i en eller flere kolonner.
Hvis en tabel har en CHECK
begrænsning på det, og du forsøger at levere data, der ikke er i overensstemmelse med CHECK
begrænsning, vil operationen mislykkes med en fejl.
Dette hjælper med at bevare dataintegriteten, fordi det hjælper med at forhindre ugyldige data i at komme ind i databasen.
Når du opretter en CHECK
begrænsning, giver du et logisk udtryk, der returnerer TRUE
eller FALSE
. Dette logiske udtryk er det, der bruges til at kontrollere dataene.
CHECK
begrænsninger ligner fremmednøgle begrænsninger, fordi de styrer de værdier, der sættes i en kolonne. Forskellen ligger dog i, hvordan de bestemmer, hvilke værdier der er gyldige:Fremmednøglebegrænsninger henter listen over gyldige værdier fra en anden tabel, mens CHECK
begrænsninger bestemmer de gyldige værdier fra et logisk udtryk.
Begrænsninger kan defineres på kolonneniveau eller tabelniveau. En begrænsning på kolonneniveau gælder kun for dataene i den kolonne. En begrænsning på tabelniveau gælder for hele rækken og kontrollerer data fra flere kolonner.
Nedenfor er eksempler på oprettelse af CHECK
på både kolonneniveau og tabelniveau begrænsninger.
Eksempel 1 – Opret en kontrolbegrænsning på kolonneniveau
Her er et eksempel på oprettelse af en grundlæggende CHECK
på kolonneniveau begrænsning på tidspunktet for oprettelse af en tabel.
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL, CONSTRAINT chkPrice CHECK (Price > 0) );
I dette tilfælde er CHECK
begrænsning angiver, at alle data i Price
kolonne skal være større end 0. Med andre ord kan prisen ikke være nul, og den kan ikke være negativ. Dette er en begrænsning på kolonneniveau, fordi den gælder for data i én kolonne.
Fordi dette er en begrænsning på kolonneniveau, kunne jeg have defineret det som en del af kolonnen (uden komma). Så jeg kunne have gjort dette:
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL CONSTRAINT chkPrice CHECK (Price > 0) );
Uanset hvad, lad os prøve at indsætte en ugyldig værdi:
INSERT INTO ConstraintTest ( Price ) VALUES ( 0 );
Resultat:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkPrice". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'Price'.
Eksempel 2 – Tilføj flere kolonner og endnu en KONTROL-begrænsning på kolonneniveau
Lad os tilføje nogle flere kolonner til vores tabel og derefter tilføje endnu en CHECK
på kolonneniveau begrænsning.
ALTER TABLE ConstraintTest ADD TeamSize tinyint NOT NULL, StartDate date NOT NULL, EndDate date NOT NULL, CONSTRAINT chkTeamSize CHECK (TeamSize >= 3 AND TeamSize <= 15) ;
En af de nye kolonner registrerer antallet af teammedlemmer. I dette tilfælde er forretningsreglen, at et team skal have mindst 3 medlemmer, men ikke mere end 15. Derfor bør databasen forhindre situationen, hvor et team har færre end 3 medlemmer eller mere end 15.
Lad os prøve at indsætte en ugyldig værdi:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 2, '2020-01-01', '1900-02-02' );
Resultat:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
Eksempel 3 – Tilføj en KONTROL-begrænsning på tabelniveau
Lad os nu tilføje en begrænsning på tabelniveau. Dette vil kontrollere data i to kolonner.
I øvrigt behøver du ikke tilføje endnu en kolonne for at tilføje en CHECK
begrænsning. Du kan blot tilføje begrænsningen af sig selv.
Eksempel:
ALTER TABLE ConstraintTest ADD CONSTRAINT chkValidEndDate CHECK (EndDate >= StartDate) ;
I dette tilfælde tilføjer jeg en begrænsning for at sikre, at slutdatoen aldrig kan være tidligere end startdatoen. Dette kontrollerer data på tværs af to kolonner og er derfor en begrænsning på tabelniveau.
Prøv at indsætte en ugyldig værdi:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 3, '2020-01-01', '1900-02-02' );
Resultat:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".
Bemærk, at for at teste denne begrænsning, var jeg nødt til at øge teammedlemmerne til 3 for at forhindre den tidligere begrænsning i at blive udløst først (CHECK
begrænsninger valideres i den rækkefølge, de oprettes).
Eksempel 4 – Ændre en CHECK-begrænsning
Du kan faktisk ikke ændre en CHECK
begrænsning. Hvis du har brug for at ændre den, skal du droppe den og oprette den med den nye definition.
Eksempel:
ALTER TABLE ConstraintTest DROP CONSTRAINT chkTeamSize; ALTER TABLE ConstraintTest ADD CONSTRAINT chkTeamSize CHECK (TeamSize >= 5 AND TeamSize <= 20) ;
Som nævnt CHECK
begrænsninger valideres i den rækkefølge, de oprettes, så dette kan påvirke, hvilken fejl der fanges først.
Derfor i dette tilfælde, hvis jeg forsøger at indsætte en ugyldig værdi (og også inkludere ugyldige datoer), vil de ugyldige datoer blive fanget først:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 4, '2020-01-01', '1900-02-02' );
Resultat:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".
Så for at tjekke min seneste begrænsning skal jeg først rette datoproblemet:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 4, '2020-01-01', '2020-02-02' );
Resultat:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
Så min seneste begrænsning fungerer som forventet.
Eksempel 5 – KONTROLLER begrænsninger og IDENTITETSkolonner
Så nu hvor vi har testet begrænsningerne, lad os gå videre og indsætte gyldige data:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 5, '2020-01-01', '2020-02-02' );
Resultat:
+--------------------+---------+------------+-------------+------------+ | ConstraintTestId | Price | TeamSize | StartDate | EndDate | |--------------------+---------+------------+-------------+------------| | 13 | 1.0000 | 5 | 2020-01-01 | 2020-02-02 | +--------------------+---------+------------+-------------+------------+
Endelig får vi et vellykket indlæg.
Du vil dog bemærke, at IDENTITY
kolonne er allerede steget til 13.
Husk, da jeg først oprettede tabellen, definerede jeg ConstraintTestId
kolonne for at bruge IDENTITY(1,1)
, hvilket betyder, at den skal starte ved 1 og automatisk stige med 1 for hver rækkeindsættelse.
Men nu hvor jeg endelig har indsat min første række, er værdien allerede 13. Det er fordi IDENTITY
kolonnen øges, selv når en CHECK
begrænsning forårsager INSERT
operation mislykkes.
Bemærk, at jeg lavede et par ekstra mislykkede indsættelser, mens jeg kom med eksemplerne til denne artikel, så værdien er steget til en højere værdi end den, du får, hvis du blot følger med trin for trin med denne artikel.
Under alle omstændigheder, lad os lave en sidste mislykket indsættelse og derefter en vellykket for at bekræfte dette.
Indsættelse mislykkedes:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 2, 4, '2020-01-02', '2020-02-03' );
Resultat:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
Vellykket indsættelse:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 2, 6, '2020-01-02', '2020-02-03' ); SELECT * FROM ConstraintTest;
Resultat:
+--------------------+---------+------------+-------------+------------+ | ConstraintTestId | Price | TeamSize | StartDate | EndDate | |--------------------+---------+------------+-------------+------------| | 13 | 1.0000 | 5 | 2020-01-01 | 2020-02-02 | | 15 | 2.0000 | 6 | 2020-01-02 | 2020-02-03 | +--------------------+---------+------------+-------------+------------+
Vi kan se, at IDENTITY
kolonne hopper fra 13 til 15, så den steg tydeligvis under den mislykkede indsættelse.
Nogle begrænsninger af CHECK-begrænsninger
Her er et par begrænsninger, du skal være opmærksom på, når du arbejder med CHECK
begrænsninger:
- Søgebetingelsen skal evalueres til et boolesk udtryk og kan ikke henvise til en anden tabel.
- Udtrykket kan ikke indeholde aliasdatatyper.
CHECK
begrænsninger kan ikke defineres på tekst , ntekst eller billede kolonner.