I SQL Server kan du skapa en CHECK
begränsning i en tabell för att ange de datavärden som är acceptabla i en eller flera kolumner.
Om en tabell har en CHECK
begränsning på det, och du försöker tillhandahålla data som inte överensstämmer med CHECK
begränsning, kommer operationen att misslyckas med ett fel.
Detta hjälper till att upprätthålla dataintegriteten, eftersom det hjälper till att förhindra att ogiltiga data kommer in i databasen.
När du skapar en CHECK
begränsning, tillhandahåller du ett logiskt uttryck som returnerar TRUE
eller FALSE
. Detta logiska uttryck är det som används för att kontrollera data.
CHECK
begränsningar liknar begränsningar för främmande nyckel eftersom de styr värdena som läggs i en kolumn. Skillnaden ligger dock i hur de avgör vilka värden som är giltiga:Främmande nyckelbegränsningar hämtar listan med giltiga värden från en annan tabell, medan CHECK
begränsningar bestämmer de giltiga värdena från ett logiskt uttryck.
Begränsningar kan definieras på kolumnnivå eller tabellnivå. En begränsning på kolumnnivå gäller bara data i den kolumnen. En begränsning på tabellnivå gäller för hela raden och kontrollerar data från flera kolumner.
Nedan finns exempel på hur du skapar CHECK
på både kolumnnivå och tabellnivå begränsningar.
Exempel 1 – Skapa en kontrollbegränsning på kolumnnivå
Här är ett exempel på hur du skapar en grundläggande CHECK
på kolumnnivå begränsning vid tidpunkten för att skapa en tabell.
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL, CONSTRAINT chkPrice CHECK (Price > 0) );
I det här fallet, CHECK
begränsning anger att all data i Price
kolumnen måste vara större än 0. Med andra ord kan priset inte vara noll och det kan inte vara negativt. Detta är en begränsning på kolumnnivå eftersom den gäller data i en kolumn.
Eftersom detta är en begränsning på kolumnnivå, kunde jag ha definierat den som en del av kolumnen (utan kommatecken). Så jag kunde ha gjort det här:
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL CONSTRAINT chkPrice CHECK (Price > 0) );
Hur som helst, låt oss försöka infoga ett ogiltigt värde:
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'.
Exempel 2 – Lägg till fler kolumner och ytterligare en kontrollbegränsning på kolumnnivå
Låt oss lägga till några fler kolumner i vår tabell och sedan lägga till ytterligare en CHECK
på kolumnnivå 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 av de nya kolumnerna registrerar antalet teammedlemmar. I det här fallet är affärsregeln att ett team måste ha minst 3 medlemmar, men inte fler än 15. Därför bör databasen förhindra situationen där ett team har färre än 3 medlemmar eller fler än 15.
Låt oss försöka infoga ett ogiltigt värde:
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'.
Exempel 3 – Lägg till en kontrollbegränsning på tabellnivå
Låt oss nu lägga till en begränsning på tabellnivå. Detta kommer att kontrollera data i två kolumner.
Förresten, du behöver inte lägga till ytterligare en kolumn för att lägga till en CHECK
begränsning. Du kan helt enkelt lägga till begränsningen själv.
Exempel:
ALTER TABLE ConstraintTest ADD CONSTRAINT chkValidEndDate CHECK (EndDate >= StartDate) ;
I det här fallet lägger jag till en begränsning för att säkerställa att slutdatumet aldrig kan vara tidigare än startdatumet. Detta kontrollerar data över två kolumner och är därför en begränsning på tabellnivå.
Försök att infoga ett ogiltigt värde:
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".
Observera att för att testa den här begränsningen var jag tvungen att öka gruppmedlemmarna till 3 för att förhindra att den tidigare begränsningen utlöses först (CHECK
begränsningar valideras i den ordning de skapas).
Exempel 4 – Ändra en CHECK-begränsning
Du kan faktiskt inte ändra en CHECK
begränsning. Om du behöver ändra den måste du släppa den och skapa den med den nya definitionen.
Exempel:
ALTER TABLE ConstraintTest DROP CONSTRAINT chkTeamSize; ALTER TABLE ConstraintTest ADD CONSTRAINT chkTeamSize CHECK (TeamSize >= 5 AND TeamSize <= 20) ;
Som nämnts, CHECK
begränsningar valideras i den ordning de skapas, så detta kan påverka vilket fel som upptäcks först.
Därför, i det här fallet, om jag försöker infoga ett ogiltigt värde (och även inkluderar ogiltiga datum), kommer de ogiltiga datumen att fångas 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å för att kontrollera min senaste begränsning måste jag åtgärda datumproblemet först:
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 senaste begränsning fungerar som förväntat.
Exempel 5 – KONTROLLERA begränsningar och IDENTITETSkolumner
Så nu när vi har testat begränsningarna, låt oss gå vidare och infoga giltiga 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 | +--------------------+---------+------------+-------------+------------+
Äntligen får vi ett lyckat inlägg.
Du kommer dock att märka att IDENTITY
kolumnen har redan ökat till 13.
Kom ihåg att när jag först skapade tabellen definierade jag ConstraintTestId
kolumn för att använda IDENTITY(1,1)
, vilket betyder att den ska börja med 1 och automatiskt öka med 1 för varje radinsättning.
Men nu när jag äntligen har infogat min första rad är värdet redan 13. Det beror på att IDENTITY
kolumnen ökas även när en CHECK
begränsning orsakar INSERT
operation misslyckas.
Observera att jag gjorde några extra misslyckade inlägg när jag kom med exemplen för den här artikeln, så värdet har ökat till ett högre värde än vad du får om du helt enkelt följer med steg för steg med den här artikeln.
Låt oss i alla fall göra en sista misslyckad infogning och sedan en framgångsrik för att bekräfta detta.
Det gick inte att infoga:
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'.
Lyckad infogning:
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 att IDENTITY
kolumnen hoppar från 13 till 15, så den ökade uppenbarligen under den misslyckade infogningen.
Några begränsningar av CHECK-begränsningar
Här är några begränsningar att tänka på när du arbetar med CHECK
begränsningar:
- Sökvillkoret måste utvärderas till ett booleskt uttryck och kan inte referera till en annan tabell.
- Uttrycket kan inte innehålla aliasdatatyper.
CHECK
begränsningar kan inte definieras på text , ntext , eller bild kolumner.