sql >> Databasteknik >  >> RDS >> Sqlserver

Hur man skapar en CHECK-begränsning i SQL Server (T-SQL-exempel)

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.

  1. Anslut till mysql i en dockningsbehållare från värden

  2. SQL Server - Fråga kortslutning?

  3. Hur man visar alla lokaler i MariaDB

  4. Sök om nummer finns i ett uttryck som:1-3,5,10-15,20