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.