sql >> Databáze >  >> RDS >> Sqlserver

Zjistěte, zda je omezení CHECK na úrovni sloupce nebo na úrovni tabulky v SQL Server (příklady T-SQL)

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ě.


  1. Přidejte znak procenta k číslu v MariaDB

  2. Jak vytvořit cizí klíč pomocí ON UPDATE CASCADE na Oracle?

  3. SQL Developer se nespustí

  4. SQL – volání uložené procedury pro každý záznam