Když vytvoříte CHECK
omezení na SQL Server, možná vás ani nenapadne přemýšlet o tom, zda se jedná o omezení na úrovni tabulky nebo omezení na úrovni sloupců.
CHECK
na úrovni tabulky omezení se vztahuje na tabulku, zatímco omezení na úrovni sloupce se vztahuje na konkrétní sloupec. S CHECK
na úrovni tabulky omezení, je to řádek, který se kontroluje při kontrole dat. S CHECK
na úrovni sloupce omezení, je zaškrtnutý konkrétní sloupec.
Obecně poznáte, zda omezení, které vytváříte, je nebo není omezení na úrovni tabulky nebo sloupce, podle definice, kterou mu zadáte. Pokud se ve výrazu kontroluje pouze jeden sloupec, bude se jednat o omezení na úrovni sloupce. Jinak to bude omezení na úrovni tabulky.
Jak ale poznáte, zda jsou vaše stávající omezení na úrovni sloupců nebo tabulky?
Můžete spustit kterýkoli z níže uvedených příkladů kódu a určit, zda jsou vaše stávající omezení na úrovni sloupců nebo tabulky. Tyto načítají všechny CHECK
omezení pro aktuální databázi, ale vždy můžete použít WHERE
klauzule k zúžení na konkrétní omezení.
Příklad 1 – Základní dotaz
Zde je jednoduchý dotaz, který vrací základní informace o všech CHECK
omezení v aktuální databázi.
Zde se dotazuji na sys.check_constraints
systémové zobrazení (které vrací řádek pro každý objekt, který je CHECK
omezení s sys.objects.type = 'C'
). Vrátím pouze čtyři sloupce (ale klidně můžete vrátit tolik sloupců, kolik chcete).
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints;
Výsledek:
+-----------------+----------------+--------------------+----------------------------------------+ | 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') | +-----------------+----------------+--------------------+----------------------------------------+
Nejrychlejším způsobem, jak určit, která omezení jsou omezení na úrovni tabulky, je hledat nulu (
0
) v
id_parent_column_id
sloupec. Cokoli s nulou je CHECK
na úrovni tabulky omezení. Nenulová hodnota znamená, že se jedná o CHECK
na úrovni sloupce omezení definované na sloupci se zadanou hodnotou ID.
V tomto příkladu tedy existují tři omezení na úrovni sloupců a jedno omezení na úrovni tabulky.
Všimněte si, že existují dvě omezení se stejným id_parent_column_id (3), tato dvě omezení však pocházejí z různých tabulek. 3 odkazuje na třetí sloupec příslušných tabulek.
Jak již bylo zmíněno, pokud chcete pouze informace o konkrétním omezení, použijte WHERE
klauzule:
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints WHERE name = 'chkPrice';
Výsledek:
+----------+----------------+--------------------+---------------+ | Name | Table | parent_column_id | Definition | |----------+----------------+--------------------+---------------| | chkPrice | ConstraintTest | 2 | ([Price]>(0)) | +----------+----------------+--------------------+---------------+
Příklad 2 – Zlepšení dotazu
Předchozí příklad můžeme vylepšit tím, že místo jeho ID vrátíme název nadřazeného sloupce. To samozřejmě vrátí název sloupce pouze pro omezení na úrovni sloupce. Pro omezení na úrovni tabulky bude vrácena hodnota 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;
Výsledek:
+-----------------+----------------+----------+----------------------------------------+ | 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') | +-----------------+----------------+----------+----------------------------------------+
Příklad 3 – Další vylepšení
Pojďme dotaz ještě upravit:
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;
Výsledek:
+-----------------+-------------+----------------+----------------+----------+----------------------------------------+ | 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') | +-----------------+-------------+----------------+----------------+----------+----------------------------------------+
Nyní se mi vrací text „Column-level“ nebo „Table-level“ v závislosti na tom, který to je.
Také používám ISNULL()
funkce pro přeměnu hodnot NULL na „(n/a)“.
A také jsem přidal is_disabled sloupec do seznamu pro případ, že by bylo některé z omezení deaktivováno. S tímto sloupcem můžete vždy zacházet stejně jako se sloupcem parent_column_id a uveďte „Ano“ nebo „Ne“ nebo „Povoleno“ nebo „Zakázáno“ nebo podobně.