Ограничения CHECK

Проверочные ограничения обеспечивают доменную целостность, ограничивая значения, которые может принимать столбец. Аналогично ограничениям внешнего ключа, они управляют значениями, которые присваиваются столбцу. Однако они по-разному определяют допустимые значения: ограничения внешнего ключа получают список допустимых значений из другой таблицы, а проверочные ограничения определяют допустимые значения по логическому выражению, которое не основано на данных в другом столбце. Например, чтобы ограничить интервал значений столбца salary, можно создать проверочное ограничение, позволяющее столбцу принимать значения только в интервале от 15 до 100 тыс. долларов. Это ограничение исключает возможность устанавливать размер зарплаты, отличный от обычного.

Проверочное ограничение можно создать с любым логическим выражением, возвращающим значение TRUE или FALSE на основе логических операторов. Для предыдущего примера логическое выражение будет выглядеть следующим образом: salary >= 15000 AND salary <= 100000.

К одному столбцу можно применять несколько проверочных ограничений. Кроме того, можно применять одно проверочное ограничение к нескольким столбцам. Для этого ограничение нужно создать на уровне таблицы. Например, с помощью проверочного ограничения на несколько столбцов можно подтвердить то, что любая строка со значением USA в столбце country/region может принимать двухсимвольное значение в столбце state. Это позволяет выполнить проверку сразу нескольких условий из одного выражения.

ПредупреждениеВнимание!

Ограничения, которые включают явное или неявное преобразование данных, могут вызывать ошибки в операциях такого рода. Например, ограничения, заданные для таблиц, которые являются исходными при переключении секций, могут приводить к ошибкам при использовании оператора ALTER TABLE...SWITCH. Следует избегать преобразования типов данных в определениях ограничений.

Ограничения проверочных ограничений

Проверочные ограничения отклоняют значения, вычисляемые в FALSE. Поскольку значения NULL вычисляются как UNKNOWN, то их наличие в выражениях может переопределить ограничение. Например, предположим, что на столбец MyColumn типа int установлено следующее ограничение: MyColumn может содержать только значение 10 (MyColumn=10). При вставке значения NULL в столбец MyColumn компонент Database Engine вставит значение NULL и не возвратит ошибку.

Проверочное ограничение возвращает TRUE, если для проверяемого условия в любой строке таблицы отсутствует значение FALSE. Если в только что созданной таблице отсутствуют строки, то любое проверочное ограничение на эту таблицу считается допустимым. В результате могут возвращаться неожиданные результаты, как в следующем примере.

CREATE TABLE CheckTbl (col1 int, col2 int);
GO
CREATE FUNCTION CheckFnctn()
RETURNS int
AS 
BEGIN
   DECLARE @retval int
   SELECT @retval = COUNT(*) FROM CheckTbl
   RETURN @retval
END;
GO
ALTER TABLE CheckTbl
ADD CONSTRAINT chkRowCount CHECK (dbo.CheckFnctn() >= 1 );
GO

Ограничение CHECK показывает, что в таблице CheckTbl должна быть хотя бы одна строка. Однако поскольку в таблице нет ни одной строки, над которой можно было бы произвести проверку ограничения, инструкция ALTER TABLE завершается успешно.

Проверочные ограничения не проверяются во время выполнения инструкций DELETE. Таким образом, выполнение инструкций DELETE над таблицами с некоторыми типами проверочных ограничений может приводить к неожиданным результатам. Например, предположим, что следующие выражения выполняются над таблицей CheckTbl.

INSERT INTO CheckTbl VALUES (10, 10)
GO
DELETE CheckTbl WHERE col1 = 10;

Инструкция DELETE выполняется успешно даже притом, что ограничением CHECK задано, что в таблице CheckTbl должна хотя бы 1 строка.