Когато създадете CHECK
ограничение в SQL Server, може дори да не мислите дали това е ограничение на ниво таблица или ограничение на ниво колона.
CHECK
на ниво таблица ограничението се прилага към таблицата, докато ограничение на ниво колона се прилага за конкретна колона. С CHECK
на ниво таблица ограничение, това е редът, който се проверява, когато проверява данните. С CHECK
на ниво колона ограничение, това е конкретната колона, която се проверява.
Като цяло ще знаете дали ограничението, което създавате, е ограничение на ниво таблица или колона според определението, което му давате. Ако в израза се проверява само една колона, това ще бъде ограничение на ниво колона. В противен случай това ще бъде ограничение на ниво таблица.
Но как да разберете дали съществуващите ви ограничения са на ниво колона или на ниво таблица?
Можете да изпълните някой от примерите за код по-долу, за да определите дали вашите съществуващи ограничения са на ниво колона или на ниво таблица. Те извличат всички CHECK
ограничения за текущата база данни, но винаги можете да използвате WHERE
клауза, за да я стесните до конкретно ограничение.
Пример 1 – Основна заявка
Ето една проста заявка, която връща основна информация за всички CHECK
ограничения в текущата база данни.
Тук правя заявка за sys.check_constraints
системен изглед (който връща ред за всеки обект, който е CHECK
ограничение, с sys.objects.type = 'C'
). Връщам само четири колони (но не се колебайте да върнете толкова колони, колкото искате).
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints;
Резултат:
+-----------------+----------------+--------------------+----------------------------------------+ | Name | Table | parent_column_id | Definition | |-----------------+----------------+--------------------+----------------------------------------| | chkPrice | ConstraintTest | 2 | ([Price]>(0)) | | chkValidEndDate | ConstraintTest | 0 | ([EndDate]>=[StartDate]) | | chkTeamSize | ConstraintTest | 3 | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | Occupation | 3 | ([JobTitle]<>'Digital Nomad') | +-----------------+----------------+--------------------+----------------------------------------+
Най-бързият начин да определите кои ограничения са ограничения на ниво таблица е да потърсите нулата (
0
) в
id_parent_column_id
колона. Всичко с нула е CHECK
на ниво таблица ограничение. Ненулева стойност показва, че това е CHECK
на ниво колона ограничение, дефинирано за колоната с посочената стойност на ID.
Така че в този пример има три ограничения на ниво колона и едно ограничение на ниво таблица.
Имайте предвид, че има две ограничения със същия parent_column_id (3), обаче, тези две ограничения са от различни таблици. 3 се отнася до третата колона на съответните им таблици.
Както споменахме, ако искате информация само за конкретно ограничение, използвайте WHERE
клауза:
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints WHERE name = 'chkPrice';
Резултат:
+----------+----------------+--------------------+---------------+ | Name | Table | parent_column_id | Definition | |----------+----------------+--------------------+---------------| | chkPrice | ConstraintTest | 2 | ([Price]>(0)) | +----------+----------------+--------------------+---------------+
Пример 2 – Подобрете заявката
Можем да подобрим предишния пример, като върнем името на родителската колона вместо само нейния идентификатор. Разбира се, това ще върне името на колоната само за ограниченията на ниво колона. За ограничения на ниво таблица ще бъде върнато NULL.
SELECT cc.name AS 'Constraint', o.name AS 'Table', ac.name AS 'Column', cc.Definition AS 'Constraint Definition' FROM sys.check_constraints cc LEFT OUTER JOIN sys.objects o ON cc.parent_object_id = o.object_id LEFT OUTER JOIN sys.all_columns ac ON cc.parent_column_id = ac.column_id AND cc.parent_object_id = ac.object_id;
Резултат:
+-----------------+----------------+----------+----------------------------------------+ | Constraint | Table | Column | Constraint Definition | |-----------------+----------------+----------+----------------------------------------| | chkPrice | ConstraintTest | Price | ([Price]>(0)) | | chkValidEndDate | ConstraintTest | NULL | ([EndDate]>=[StartDate]) | | chkTeamSize | ConstraintTest | TeamSize | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | Occupation | JobTitle | ([JobTitle]<>'Digital Nomad') | +-----------------+----------------+----------+----------------------------------------+
Пример 3 – Допълнителни подобрения
Нека настроим още малко заявката:
SELECT cc.name AS 'Constraint', cc.is_disabled AS 'Disabled?', CASE WHEN cc.parent_column_id = 0 THEN 'Table-level' ELSE 'Column-level' END AS 'Table/Column', o.name AS 'Table', ISNULL(ac.name, '(n/a)') AS 'Column', cc.Definition AS 'Constraint Definition' FROM sys.check_constraints cc LEFT OUTER JOIN sys.objects o ON cc.parent_object_id = o.object_id LEFT OUTER JOIN sys.all_columns ac ON cc.parent_column_id = ac.column_id AND cc.parent_object_id = ac.object_id;
Резултат:
+-----------------+-------------+----------------+----------------+----------+----------------------------------------+ | Constraint | Disabled? | Table/Column | Table | Column | Constraint Definition | |-----------------+-------------+----------------+----------------+----------+----------------------------------------| | chkPrice | 0 | Column-level | ConstraintTest | Price | ([Price]>(0)) | | chkValidEndDate | 0 | Table-level | ConstraintTest | (n/a) | ([EndDate]>=[StartDate]) | | chkTeamSize | 0 | Column-level | ConstraintTest | TeamSize | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | 0 | Column-level | Occupation | JobTitle | ([JobTitle]<>'Digital Nomad') | +-----------------+-------------+----------------+----------------+----------+----------------------------------------+
Така че сега се връща текстът „на ниво колона“ или „на ниво таблица“, в зависимост от това кой е.
Използвам и ISNULL()
функция за превръщане на всички NULL стойности в „(n/a)“.
И също така добавих is_disabled колона в списъка, само в случай, че някое от ограниченията е деактивирано. Винаги можете да дадете на тази колона същото третиране като parent_column_id колона и представете „Да“ или „Не“, или „Активирано“ или „Деактивирано“ или подобно.