136 votes

La contrainte CHECK dans MySQL ne fonctionne pas

J'ai d'abord créé une table comme

CREATE TABLE Customer (
  SD integer CHECK (SD > 0),
  Last_Name varchar (30),
  First_Name varchar(30)
);

et a ensuite inséré des valeurs dans ce tableau

INSERT INTO Customer values ('-2','abc','zz');

MySQL ne montre pas d'erreur, il a accepté les valeurs.

0 votes

Partiellement d'accord. Étant donné que vous avez essayé de l'utiliser, on peut supposer que vous posiez les deux questions. En fait, la réponse que vous avez acceptée explique principalement pourquoi il ne fonctionne pas.

1 votes

Vous pouvez voter sur cette demande de fonctionnalité : bugs.mysql.com/bug.php?id=3464 mais elle n'a pas reçu d'attention depuis une décennie.

11 votes

Vous pouvez utiliser les contraintes CHECK dans MariaDB à partir de version 10.2.1 .

154voto

David Kerins Points 391

MySQL 8.0.16 est la première version qui prend en charge les contraintes CHECK.

Lire https://dev.mysql.com/doc/refman/8.0/en/create-table-check-constraints.html

Si vous utilisez MySQL 8.0.15 ou une version antérieure, l'option Manuel de référence MySQL dit :

El CHECK est analysée mais ignorée par tous les moteurs de stockage.

Essayez une gâchette...

mysql> delimiter //
mysql> CREATE TRIGGER trig_sd_check BEFORE INSERT ON Customer 
    -> FOR EACH ROW 
    -> BEGIN 
    -> IF NEW.SD<0 THEN 
    -> SET NEW.SD=0; 
    -> END IF; 
    -> END
    -> //
mysql> delimiter ;

J'espère que cela vous aidera.

9 votes

Vous trouverez ici comment déclencher une erreur à la place : stackoverflow.com/a/7189396/1144966

45 votes

C'est l'une des nombreuses raisons pour lesquelles j'utiliserai toujours PostgreSQL plutôt que MySQL si j'ai le choix.

6 votes

Je me demande si un développement de 10 ou 15 minutes dans MySQL permettrait d'afficher un avertissement si l'analyseur syntaxique rencontre un fichier CHECK contrainte définie. Ahhh, ce serait trop simple...

76voto

Michel Feldheim Points 7222

Malheureusement, MySQL ne prend pas en charge les contraintes de contrôle SQL. Vous pouvez les définir dans votre requête DDL pour des raisons de compatibilité, mais elles sont tout simplement ignorées.

Il existe une alternative simple

Vous pouvez créer BEFORE INSERT y BEFORE UPDATE des déclencheurs qui provoquent une erreur ou définissent le champ à sa valeur par défaut lorsque les exigences des données ne sont pas satisfaites.

Exemple pour BEFORE INSERT fonctionne après MySQL 5.5

DELIMITER $$
CREATE TRIGGER `test_before_insert` BEFORE INSERT ON `Test`
FOR EACH ROW
BEGIN
    IF CHAR_LENGTH( NEW.ID ) < 4 THEN
        SIGNAL SQLSTATE '12345'
            SET MESSAGE_TEXT := 'check constraint on Test.ID failed';
    END IF;
END$$   
DELIMITER ;  

Avant MySQL 5.5, vous deviez provoquer une erreur, par exemple en appelant une procédure non définie.

Dans les deux cas, cela provoque un retour en arrière implicite de la transaction. MySQL n'autorise pas l'instruction ROLLBACK elle-même dans les procédures et les déclencheurs.

Si vous ne voulez pas annuler la transaction (INSERT / UPDATE devrait passer même si la "contrainte de vérification" a échoué), vous pouvez écraser la valeur en utilisant la méthode suivante SET NEW.ID = NULL qui donnera à l'id la valeur par défaut du champ, ce qui n'a pas vraiment de sens pour un id.

Edit : J'ai supprimé la citation perdue.

Concernant le := opérateur :

Contrairement à = le := n'est jamais interprété comme un opérateur de comparaison. Cela signifie que vous pouvez utiliser := dans toute instruction SQL valide (pas seulement dans les instructions SET) pour attribuer une valeur à une variable.

https://dev.mysql.com/doc/refman/5.6/en/assignment-operators.html

Concernant les citations de l'identificateur de backtick :

Le caractère de citation d'identification est le backtick ("`").

Si le mode SQL ANSI_QUOTES est activé, il est également possible de citer les identifiants entre guillemets doubles.

http://dev.mysql.com/doc/refman/5.6/en/identifiers.html

7 votes

...pas très simple, du moins comparé à CHECK :(. Quelques conseils : net.tutsplus.com/tutoriels/bases de données/ , sitepoint.com/how-to-create-mysql-triggers

0 votes

Ugh ça a l'air très volumineux. Je pense que je préfère créer un tuple en python et vérifier les valeurs là plutôt que de mettre ça dedans.

0 votes

Petite question : pourquoi cela ne fonctionne-t-il pas sans paramétrer l'option DELIMITER ?

53voto

ypercube Points 62714

CHECK sont ignorées par MySQL, comme l'explique un minuscule commentaire dans la documentation : CREATE TABLE

El CHECK est analysée mais ignorée par tous les moteurs de stockage.

2 votes

@thefiloe : Correct, dans d'autres SGBD avec une implémentation correcte de CHECK si le CHECK s'évalue à FALSE l'insertion (ou la mise à jour) n'est pas effectuée et une erreur se produit.

0 votes

Corrigé dans MariaDB (voir cette réponse) stackoverflow.com/a/44333349 ).

0 votes

@Jérôme Je sais, j'ai des réponses (plus récentes) qui incluent des améliorations dans ce domaine (il y avait d'autres moyens de contourner ce problème, à la fois dans MariaDB et MySQL, avant que MariaDB n'implémente correctement les contraintes CHECK). Ce dont je ne suis pas sûr, c'est si je dois aller éditer toutes mes anciennes réponses !

16voto

ryanprayogo Points 5058

El CHECK ne semble pas être implémentée dans MySQL.

Voir ce rapport de bogue : https://bugs.mysql.com/bug.php?id=3464

1 votes

Corrigé dans MariaDB (voir cette réponse stackoverflow.com/a/44333349 ).

9voto

Markus Barthlen Points 11

Comme mentionné par joanq, MariaDB semble maintenant supporter les contraintes CHECK entre autres :

" Prise en charge de CHECK CONSTRAINT ( MDEV-7563 )."

https://mariadb.com/kb/en/mariadb/mariadb-1021-release-notes/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X