web-dev-qa-db-fra.com

Qu'est-ce qu'une CONTRAINTE AVEC CHECK CHECK?

J'ai du T-SQL généré automatiquement, qui est probablement valide, mais je ne comprends pas vraiment.

ALTER TABLE [dbo].[MyTable]
WITH CHECK
CHECK CONSTRAINT [My_FORIEGN_KEY];

Je sais ce qu'est une contrainte de clé étrangère, mais quelle est la CHECK CHECK?

21
BanksySan

La page de documentation de MSDN sur ALTER TABLE explique ceci:

  • ALTER TABLE: modifie la structure de la table
    (et certaines des actions/modifications possibles sont):
    • CHECK CONSTRAINT ..: activer la contrainte
    • NOCHECK CONSTRAINT ..: désactiver la contrainte
      Il existe également des étapes supplémentaires facultatives à effectuer lors de la création/activation/désactivation d'une contrainte:
      • WITH CHECK: vérifie également la contrainte
      • WITH NOCHECK: ne vérifie pas la contrainte

Dans leurs mots:

| [ WITH { CHECK | NOCHECK } ] { CHECK | NOCHECK } CONSTRAINT   
    { ALL | constraint_name [ ,...n ] }

...

WITH CHECK | WITH NOCHECK Spécifie si les données de la table sont ou non validées contre un _ nouvellement ajouté ou réactivé FOREIGN KEY ou CHECK contrainte . Si non spécifié, WITH CHECK est supposé pour les nouvelles contraintes, et WITH NOCHECK est supposé pour les contraintes réactivées.

Si vous ne souhaitez pas vérifier les nouveaux CHECK ou FOREIGN KEY contraintes par rapport aux données existantes, utilisez WITH NOCHECK. Nous vous déconseillons de le faire, sauf dans de rares cas. La nouvelle contrainte sera évaluée dans toutes les mises à jour de données ultérieures. Toute violation de contrainte supprimée par WITH NOCHECK lorsque la contrainte est ajoutée peut entraîner l'échec des futures mises à jour si elles mettent à jour les lignes avec des données non conformes à la contrainte.

L'optimiseur de requêtes ne prend pas en compte les contraintes définies WITH NOCHECK. Ces contraintes sont ignorées jusqu'à ce qu'elles soient réactivées à l'aide de ALTER TABLE table WITH CHECK CHECK CONSTRAINT ALL.

...

{ CHECK | NOCHECK } CONSTRAINT
Spécifie que nom_contrainte est activé ou désactivé. Cette option ne peut être utilisée qu'avec FOREIGN KEY et CHECK contraintes. Lorsque NOCHECK est spécifié, la contrainte est désactivée et les insertions ou mises à jour futures de la colonne ne sont pas validées par rapport aux conditions de contrainte. DEFAULT, PRIMARY KEY et UNIQUE les contraintes ne peuvent pas être désactivées.

Testez dans dbfiddle :

CREATE TABLE a (aid INT PRIMARY KEY);

ALLER

INSERT INTO a (aid)
VALUES (1), (2), (3) ;

ALLER

 3 lignes affectées 
CREATE TABLE b 
( aid INT,
  bid INT PRIMARY KEY,
  CONSTRAINT [My_FORIEGN_KEY]
    FOREIGN KEY (aid) REFERENCES a (aid)
) ;

ALLER

INSERT INTO b (aid, bid)
VALUES
  (1, 11),
  (1, 12),
  (2, 21), 
  (3, 31) ;

ALLER

 4 lignes affectées 
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

ALLER

 Msg 547 Niveau 16 État 0 Ligne 1 
 L'instruction INSERT était en conflit avec la contrainte FOREIGN KEY "My_FORIEGN_KEY". Le conflit s'est produit dans la base de données "fiddle_792fce5de09f42908c3a0f91421f3522", table "dbo.a", colonne 'aide'. 
 Msg 3621 niveau 0 état 0 ligne 1 
 L'instruction a été terminée. 
SELECT * FROM b ;

ALLER

 aide | enchère 
 -: | -: 
 1 | 11 
 1 | 12 
 2 | 21 
 3 | 31 
ALTER TABLE b NOCHECK CONSTRAINT [My_FORIEGN_KEY];   --disable

ALLER

INSERT INTO b (aid, bid)
VALUES
  (4, 41),
  (4, 42) ;

ALLER

 2 lignes affectées 
SELECT * FROM b ;

ALLER

 aide | enchère 
 -: | -: 
 1 | 11 
 1 | 12 
 2 | 21 
 3 | 31 
 4 | 41 
 4 | 42 
ALTER TABLE b WITH NOCHECK CHECK CONSTRAINT [My_FORIEGN_KEY];  
-- enable constraint without checking existing data

ALLER

SELECT * FROM b ;

ALLER

 aide | enchère 
 -: | -: 
 1 | 11 
 1 | 12 
 2 | 21 
 3 | 31 
 4 | 41 
 4 | 42 
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

ALLER

 Msg 547 Niveau 16 État 0 Ligne 1 
 L'instruction INSERT était en conflit avec la contrainte FOREIGN KEY "My_FORIEGN_KEY". Le conflit s'est produit dans la base de données "fiddle_792fce5de09f42908c3a0f91421f3522", table "dbo.a", colonne 'aide'. 
 Msg 3621 niveau 0 état 0 ligne 1 
 L'instruction a été terminée. 
SELECT * FROM b ;

ALLER

 aide | enchère 
 -: | -: 
 1 | 11 
 1 | 12 
 2 | 21 
 3 | 31 
 4 | 41 
 4 | 42 
ALTER TABLE b WITH CHECK CHECK CONSTRAINT [My_FORIEGN_KEY];  
-- check existing data and enable constraint 

ALLER

 Msg 547 Niveau 16 État 0 Ligne 1 
 L'instruction ALTER TABLE était en conflit avec la contrainte FOREIGN KEY "My_FORIEGN_KEY". Le conflit s'est produit dans la base de données "fiddle_792fce5de09f42908c3a0f91421f3522", table "dbo.a", colonne 'aide'. 
31
ypercubeᵀᴹ

Pensez à lire l'article ici: https://msdn.Microsoft.com/en-us/library/ms190273.aspx

Il nous dit: "L'optimiseur de requêtes ne prend pas en compte les contraintes définies AVEC NOCHECK. Ces contraintes sont ignorées jusqu'à ce qu'elles soient réactivées à l'aide de la table ALTER TABLE AVEC CHECK CHECK CONSTRAINT ALL '

Considérez également ce fil sur StackOverflow: https://stackoverflow.com/questions/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint

1
George K