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

Comment créer une contrainte CHECK dans SQL Server (exemples T-SQL)

Dans SQL Server, vous pouvez créer un CHECK contrainte dans une table pour spécifier les valeurs de données acceptables dans une ou plusieurs colonnes.

Si une table a un CHECK contrainte dessus, et vous essayez de fournir des données qui ne sont pas conformes à la CHECK contrainte, l'opération échouera avec une erreur.

Cela aide à maintenir l'intégrité des données, car cela aide à empêcher que des données non valides entrent dans la base de données.

Lorsque vous créez un CHECK contrainte, vous fournissez une expression logique qui renvoie TRUE ou FALSE . Cette expression logique est utilisée pour vérifier les données.

CHECK Les contraintes sont similaires aux contraintes de clé étrangère car elles contrôlent les valeurs placées dans une colonne. Cependant, la différence réside dans la manière dont elles déterminent les valeurs valides :les contraintes de clé étrangère obtiennent la liste des valeurs valides d'une autre table, tandis que CHECK les contraintes déterminent les valeurs valides à partir d'une expression logique.

Les contraintes peuvent être définies au niveau de la colonne ou au niveau de la table. Une contrainte au niveau de la colonne s'applique uniquement aux données de cette colonne. Une contrainte au niveau de la table s'applique à toute la ligne et vérifie les données de plusieurs colonnes.

Vous trouverez ci-dessous des exemples de création de CHECK au niveau de la colonne et de la table. contraintes.

Exemple 1 – Créer une contrainte CHECK au niveau de la colonne

Voici un exemple de création d'un CHECK de base au niveau de la colonne contrainte lors de la création d'une table.

CREATE TABLE ConstraintTest
(
  ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  Price smallmoney NOT NULL,
  CONSTRAINT chkPrice CHECK (Price > 0)
);

Dans ce cas, le CHECK contrainte spécifie que toutes les données du Price doit être supérieur à 0. En d'autres termes, le prix ne peut pas être nul et il ne peut pas être négatif. Il s'agit d'une contrainte au niveau de la colonne, car elle s'applique aux données d'une seule colonne.

Comme il s'agit d'une contrainte au niveau de la colonne, j'aurais pu la définir dans le cadre de la colonne (sans la virgule). Donc j'aurais pu faire ça :

CREATE TABLE ConstraintTest
(
  ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  Price smallmoney NOT NULL CONSTRAINT chkPrice CHECK (Price > 0)
);

Dans tous les cas, essayons d'insérer une valeur invalide :

INSERT INTO ConstraintTest ( Price )
VALUES ( 0 );

Résultat :

Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkPrice". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'Price'.

Exemple 2 – Ajouter d'autres colonnes et une autre contrainte CHECK au niveau de la colonne

Ajoutons quelques colonnes supplémentaires à notre table, puis ajoutons un autre CHECK au niveau de la colonne contrainte.

ALTER TABLE ConstraintTest
ADD 
  TeamSize tinyint NOT NULL,
  StartDate date NOT NULL,
  EndDate date NOT NULL,
  CONSTRAINT chkTeamSize CHECK (TeamSize >= 3 AND TeamSize <= 15)
  ;

L'une des nouvelles colonnes enregistre le nombre de membres de l'équipe. Dans ce cas, la règle métier est qu'une équipe doit avoir au moins 3 membres, mais pas plus de 15. Par conséquent, la base de données doit empêcher la situation où une équipe compte moins de 3 membres ou plus de 15.

Essayons d'insérer une valeur invalide :

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 2, '2020-01-01', '1900-02-02' );

Résultat :

Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.

Exemple 3 – Ajouter une contrainte CHECK au niveau de la table

Ajoutons maintenant une contrainte au niveau de la table. Cela vérifiera les données dans deux colonnes.

Au fait, vous n'avez pas besoin d'ajouter une autre colonne pour ajouter un CHECK contrainte. Vous pouvez simplement ajouter la contrainte par elle-même.

Exemple :

ALTER TABLE ConstraintTest
  ADD CONSTRAINT chkValidEndDate 
  CHECK (EndDate >= StartDate)
  ;

Dans ce cas, j'ajoute une contrainte pour garantir que la date de fin ne peut jamais être antérieure à la date de début. Ceci vérifie les données sur deux colonnes et est donc une contrainte au niveau de la table.

Essayez d'insérer une valeur invalide :

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 3, '2020-01-01', '1900-02-02' );

Résultat :

Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".

Notez que pour tester cette contrainte, j'ai dû augmenter les membres de l'équipe à 3 pour éviter que la contrainte précédente ne soit déclenchée en premier (CHECK les contraintes sont validées dans l'ordre de leur création).

Exemple 4 - Modifier une contrainte CHECK

Vous ne pouvez pas réellement modifier un CHECK contrainte. Si vous devez le modifier, vous devrez le supprimer et le créer avec la nouvelle définition.

Exemple :

ALTER TABLE ConstraintTest 
  DROP CONSTRAINT chkTeamSize;

ALTER TABLE ConstraintTest
  ADD CONSTRAINT chkTeamSize 
  CHECK (TeamSize >= 5 AND TeamSize <= 20)
  ;

Comme mentionné, CHECK les contraintes sont validées dans l'ordre dans lequel elles sont créées, ce qui peut affecter l'erreur détectée en premier.

Par conséquent, dans ce cas, si j'essaie d'insérer une valeur invalide (et d'inclure également des dates invalides), les dates invalides seront interceptées en premier :

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 4, '2020-01-01', '1900-02-02' );

Résultat :

Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".

Donc, afin de vérifier ma dernière contrainte, je dois d'abord résoudre le problème de date :

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 4, '2020-01-01', '2020-02-02' );

Résultat :

Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.

Ma dernière contrainte fonctionne donc comme prévu.

Exemple 5 – CHECK Constraints et colonnes IDENTITY

Maintenant que nous avons testé les contraintes, allons-y et insérons des données valides :

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 5, '2020-01-01', '2020-02-02' );

Résultat :

+--------------------+---------+------------+-------------+------------+
| ConstraintTestId   | Price   | TeamSize   | StartDate   | EndDate    |
|--------------------+---------+------------+-------------+------------|
| 13                 | 1.0000  | 5          | 2020-01-01  | 2020-02-02 |
+--------------------+---------+------------+-------------+------------+

Enfin, nous obtenons une insertion réussie.

Cependant, vous remarquerez que le IDENTITY la colonne a déjà augmenté à 13.

Rappelez-vous que lorsque j'ai créé la table pour la première fois, j'ai défini le ConstraintTestId colonne pour utiliser IDENTITY(1,1) , ce qui signifie qu'il doit commencer à 1 et s'incrémenter automatiquement de 1 à chaque insertion de ligne.

Mais maintenant que j'ai enfin inséré ma première ligne, la valeur est déjà 13. C'est parce que le IDENTITY la colonne est incrémentée même lorsqu'un CHECK contrainte provoque le INSERT l'opération échoue.

Notez que j'ai fait quelques insertions ratées supplémentaires lors de la création des exemples pour cet article, de sorte que la valeur a augmenté à une valeur supérieure à celle que vous obtiendrez si vous suivez simplement étape par étape cet article.

Dans tous les cas, faisons une dernière insertion ratée, puis une réussie pour le confirmer.

Échec de l'insertion :

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 2, 4, '2020-01-02', '2020-02-03' );

Résultat :

Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.

Insertion réussie :

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 2, 6, '2020-01-02', '2020-02-03' );

SELECT * FROM ConstraintTest;

Résultat :

+--------------------+---------+------------+-------------+------------+
| ConstraintTestId   | Price   | TeamSize   | StartDate   | EndDate    |
|--------------------+---------+------------+-------------+------------|
| 13                 | 1.0000  | 5          | 2020-01-01  | 2020-02-02 |
| 15                 | 2.0000  | 6          | 2020-01-02  | 2020-02-03 |
+--------------------+---------+------------+-------------+------------+

Nous pouvons voir que le IDENTITY la colonne saute de 13 à 15, elle a donc évidemment été incrémentée lors de l'échec de l'insertion.

Quelques restrictions des contraintes CHECK

Voici quelques restrictions à prendre en compte lorsque vous travaillez avec CHECK contraintes :

  • La condition de recherche doit correspondre à une expression booléenne et ne peut pas faire référence à une autre table.
  • L'expression ne peut pas contenir de types de données d'alias.
  • CHECK les contraintes ne peuvent pas être définies sur le texte , texte , ou image colonnes.