В SQL Server можете да създадете CHECK
ограничение в таблица, за да посочите стойностите на данните, които са приемливи в една или повече колони.
Ако таблица има CHECK
ограничение върху него и се опитвате да предоставите данни, които не отговарят на CHECK
ограничение, операцията ще се провали с грешка.
Това помага да се поддържа целостта на данните, защото помага да се предотврати навлизането на невалидни данни в базата данни.
Когато създадете CHECK
ограничение предоставяте логически израз, който връща TRUE
или FALSE
. Този логически израз се използва за проверка на данните.
CHECK
ограниченията са подобни на ограниченията на външния ключ, защото контролират стойностите, които се поставят в колона. Разликата обаче е в това как определят кои стойности са валидни:ограниченията на външния ключ получават списъка с валидни стойности от друга таблица, докато CHECK
ограниченията определят валидните стойности от логически израз.
Ограниченията могат да бъдат дефинирани на ниво колона или на ниво таблица. Ограничение на ниво колона се прилага само за данните в тази колона. Ограничение на ниво таблица се прилага за целия ред и проверява данни от множество колони.
По-долу са дадени примери за създаване както на ниво колона, така и на ниво таблица CHECK
ограничения.
Пример 1 – Създайте ограничение CHECK на ниво колона
Ето пример за създаване на основен CHECK
на ниво колона ограничение в момента на създаване на таблица.
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL, CONSTRAINT chkPrice CHECK (Price > 0) );
В този случай CHECK
ограничението указва, че всички данни в Price
колоната трябва да е по-голяма от 0. С други думи, цената не може да бъде нула и не може да бъде отрицателна. Това е ограничение на ниво колона, защото се прилага за данни в една колона.
Тъй като това е ограничение на ниво колона, бих могъл да го дефинирам като част от колоната (без запетаята). Така че можех да направя това:
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL CONSTRAINT chkPrice CHECK (Price > 0) );
Така или иначе, нека се опитаме да вмъкнем невалидна стойност:
INSERT INTO ConstraintTest ( Price ) VALUES ( 0 );
Резултат:
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'.
Пример 2 – Добавете още колони и друго ограничение за ПРОВЕРКА на ниво колона
Нека добавим още няколко колони към нашата таблица и след това добавим още една колона CHECK
ограничение.
ALTER TABLE ConstraintTest ADD TeamSize tinyint NOT NULL, StartDate date NOT NULL, EndDate date NOT NULL, CONSTRAINT chkTeamSize CHECK (TeamSize >= 3 AND TeamSize <= 15) ;
Една от новите колони записва броя на членовете на екипа. В този случай бизнес правилото е, че екипът трябва да има най-малко 3 членове, но не повече от 15. Следователно базата данни трябва да предотвратява ситуацията, при която екипът има по-малко от 3 или повече от 15 членове.
Нека се опитаме да вмъкнем невалидна стойност:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 2, '2020-01-01', '1900-02-02' );
Резултат:
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'.
Пример 3 – Добавете ограничение CHECK на ниво таблица
Сега нека добавим ограничение на ниво таблица. Това ще провери данните в две колони.
Между другото, не е нужно да добавяте друга колона, за да добавите CHECK
ограничение. Можете просто да добавите ограничението от само себе си.
Пример:
ALTER TABLE ConstraintTest ADD CONSTRAINT chkValidEndDate CHECK (EndDate >= StartDate) ;
В този случай добавям ограничение, за да гарантирам, че крайната дата никога не може да бъде по-рано от началната. Това е проверка на данни в две колони и следователно е ограничение на ниво таблица.
Опитайте да въведете невалидна стойност:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 3, '2020-01-01', '1900-02-02' );
Резултат:
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".
Имайте предвид, че за да тествам това ограничение, трябваше да увелича членовете на екипа до 3, за да предотвратя първото задействане на предишното ограничение (CHECK
ограниченията се валидират в реда, в който са създадени).
Пример 4 – Промяна на ограничение CHECK
Всъщност не можете да промените CHECK
ограничение. Ако трябва да го промените, ще трябва да го пуснете и да го създадете с новата дефиниция.
Пример:
ALTER TABLE ConstraintTest DROP CONSTRAINT chkTeamSize; ALTER TABLE ConstraintTest ADD CONSTRAINT chkTeamSize CHECK (TeamSize >= 5 AND TeamSize <= 20) ;
Както бе споменато, CHECK
Ограниченията се валидират в реда, в който са създадени, така че това може да повлияе коя грешка е уловена първа.
Следователно в този случай, ако се опитам да вмъкна невалидна стойност (и също така да включа невалидни дати), невалидните дати ще бъдат уловени първи:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 4, '2020-01-01', '1900-02-02' );
Резултат:
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".
Така че, за да проверя последното си ограничение, първо ще трябва да поправя проблема с датата:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 4, '2020-01-01', '2020-02-02' );
Резултат:
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'.
Така че последното ми ограничение работи според очакванията.
Пример 5 – ПРОВЕРКА на ограничения и колони ИДЕНТИЧНОСТ
Така че сега, след като тествахме ограниченията, нека да продължим и да вмъкнем валидни данни:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 5, '2020-01-01', '2020-02-02' );
Резултат:
+--------------------+---------+------------+-------------+------------+ | ConstraintTestId | Price | TeamSize | StartDate | EndDate | |--------------------+---------+------------+-------------+------------| | 13 | 1.0000 | 5 | 2020-01-01 | 2020-02-02 | +--------------------+---------+------------+-------------+------------+
Накрая получаваме успешно вмъкване.
Въпреки това ще забележите, че IDENTITY
колоната вече се е увеличила до 13.
Не забравяйте, че когато за първи път създадох таблицата, дефинирах ConstraintTestId
колона, за да използвате IDENTITY(1,1)
, което означава, че трябва да започне от 1 и автоматично да се увеличава с 1 с всяко вмъкване на ред.
Но сега, когато най-накрая вмъкнах първия си ред, стойността вече е 13. Това е защото IDENTITY
колоната се увеличава дори когато CHECK
ограничението причинява INSERT
операция е неуспешна.
Имайте предвид, че направих няколко допълнителни неуспешни вмъквания, докато измислих примерите за тази статия, така че стойността се увеличи до по-висока стойност от тази, която ще получите, ако просто следвате стъпка по стъпка с тази статия.
Във всеки случай, нека направим едно последно неуспешно вмъкване и след това успешно, за да потвърдим това.
Неуспешно вмъкване:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 2, 4, '2020-01-02', '2020-02-03' );
Резултат:
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'.
Успешно вмъкване:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 2, 6, '2020-01-02', '2020-02-03' ); SELECT * FROM ConstraintTest;
Резултат:
+--------------------+---------+------------+-------------+------------+ | 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 | +--------------------+---------+------------+-------------+------------+
Можем да видим, че IDENTITY
колоната скача от 13 на 15, така че очевидно се е увеличила по време на неуспешното вмъкване.
Някои ограничения на ограниченията на CHECK
Ето няколко ограничения, които трябва да имате предвид, когато работите с CHECK
ограничения:
- Условието за търсене трябва да се оценява като булев израз и не може да препраща към друга таблица.
- Изразът не може да съдържа типове данни за псевдоним.
CHECK
ограниченията не могат да бъдат дефинирани за текст , ntext , или изображение колони.