Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Découvrez si une contrainte CHECK est au niveau de la colonne ou au niveau de la table dans SQL Server (exemples T-SQL)

Lorsque vous créez un CHECK contrainte dans SQL Server, vous ne vous demandez peut-être même pas s'il s'agit d'une contrainte au niveau de la table ou d'une contrainte au niveau de la colonne.

Un CHECK au niveau de la table contrainte s'applique à la table, tandis qu'une contrainte au niveau de la colonne s'applique à une colonne spécifique. Avec un CHECK au niveau de la table contrainte, c'est la ligne qui est vérifiée lors de la vérification des données. Avec un CHECK au niveau de la colonne contrainte, c'est la colonne spécifique qui est vérifiée.

Généralement, vous saurez si la contrainte que vous créez est une contrainte au niveau de la table ou de la colonne par la définition que vous lui donnez. Si une seule colonne est vérifiée dans l'expression, il s'agira d'une contrainte au niveau de la colonne. Sinon, ce sera une contrainte au niveau de la table.

Mais comment savoir si vos contraintes existantes sont au niveau des colonnes ou au niveau des tables ?

Vous pouvez exécuter n'importe lequel des exemples de code ci-dessous pour déterminer si vos contraintes existantes sont au niveau de la colonne ou au niveau de la table. Ceux-ci récupèrent tous les CHECK contraintes pour la base de données courante, mais vous pouvez toujours utiliser un WHERE clause pour la réduire à une contrainte spécifique.

Exemple 1 – Requête de base

Voici une requête simple qui renvoie des informations de base sur tous les CHECK contraintes dans la base de données courante.

Ici, j'interroge le sys.check_constraints vue système (qui renvoie une ligne pour chaque objet qui est un CHECK contrainte, avec sys.objects.type = 'C' ). Je ne renvoie que quatre colonnes (mais n'hésitez pas à renvoyer autant de colonnes que vous le souhaitez).

SELECT 
  Name,
  OBJECT_NAME(parent_object_id) AS 'Table',
  parent_column_id,
  Definition
FROM sys.check_constraints;

Résultat :

+-----------------+----------------+--------------------+----------------------------------------+
| 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')          |
+-----------------+----------------+--------------------+----------------------------------------+

Le moyen le plus rapide de déterminer quelles contraintes sont des contraintes au niveau de la table consiste à rechercher le zéro ( 0 ) dans parent_column_id colonne. Tout ce qui contient un zéro est un CHECK au niveau de la table contrainte. Une valeur différente de zéro indique qu'il s'agit d'un CHECK au niveau de la colonne contrainte définie sur la colonne avec la valeur d'ID spécifiée.

Ainsi, dans cet exemple, il y a trois contraintes au niveau des colonnes et une contrainte au niveau de la table.

Notez qu'il existe deux contraintes avec le même parent_column_id (3), cependant, ces deux contraintes proviennent de tables différentes. Le 3 fait référence à la troisième colonne de leurs tableaux respectifs.

Comme mentionné, si vous voulez uniquement des informations sur une contrainte spécifique, utilisez un WHERE clause :

SELECT 
  Name,
  OBJECT_NAME(parent_object_id) AS 'Table',
  parent_column_id,
  Definition
FROM sys.check_constraints
WHERE name = 'chkPrice';

Résultat :

+----------+----------------+--------------------+---------------+
| Name     | Table          | parent_column_id   | Definition    |
|----------+----------------+--------------------+---------------|
| chkPrice | ConstraintTest | 2                  | ([Price]>(0)) |
+----------+----------------+--------------------+---------------+

Exemple 2 – Améliorer la requête

Nous pouvons améliorer l'exemple précédent en renvoyant le nom de la colonne parente au lieu de simplement son ID. Bien sûr, cela renverra le nom de la colonne uniquement pour les contraintes au niveau de la colonne. Pour les contraintes au niveau de la table, NULL sera renvoyé.

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;

Résultat :

+-----------------+----------------+----------+----------------------------------------+
| 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')          |
+-----------------+----------------+----------+----------------------------------------+

Exemple 3 – Autres améliorations

Ajustons encore la requête :

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;

Résultat :

+-----------------+-------------+----------------+----------------+----------+----------------------------------------+
| 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')          |
+-----------------+-------------+----------------+----------------+----------+----------------------------------------+

J'ai donc maintenant le texte "Column-level" ou "Table-level" renvoyé, selon lequel il s'agit.

J'utilise aussi le ISNULL() fonction pour transformer toutes les valeurs NULL en "(n/a)".

Et j'ai également ajouté le is_disabled colonne à la liste, juste au cas où l'une des contraintes aurait été désactivée. Vous pouvez toujours donner à cette colonne le même traitement que le parent_column_id colonne et présentez "Oui" ou "Non" ou "Activé" ou "Désactivé" ou similaire.