Puis-je m'assurer que deux colonnes n'ont pas la même valeur

11

Si j'ai une table qui ressemble à ça

CREATE TABLE foo (
   id INT NOT NULL AUTO_INCREMENT,
   aa INT NOT NULL,
   bb INT NOT NULL,
   PRIMARY KEY (id),
   UNIQUE KEY (aa, bb),
   CONSTRAINT aa_ref FOREIGN KEY (aa) REFERENCES bar (id),
   CONSTRAINT bb_ref FOREIGN KEY (bb) REFERENCES bar (id)
)

Existe-t-il un moyen de s'assurer qu'en aa != bbplus d'utiliser la logique au niveau de l'application ou de forcer un déclencheur à échouer AVANT L'INSERTION?

Nifle
la source

Réponses:

3

MySQL ne prend pas CHECKdirectement en charge les contrsaints, mais si vous avez une version suffisamment récente, il prend en charge les déclencheurs et la génération d'erreurs via SIGNAL, vous pouvez donc définir BEFORE INSERTet BEFORE UPDATEdéclencher des vérifications des données et générer des erreurs si la contrainte prévue n'est pas satisfaite.

Bien sûr, cela sera moins efficace que la prise en charge native des contraintes de vérification, donc si vous effectuez un volume élevé d'écritures dans cette structure, assurez-vous d'analyser la différence de performances provoquée par le déclencheur au cas où cela nuirait trop à votre application.

David Spillett
la source
8

Non, tu ne peux pas. Dans la plupart des SGBD (Postgres, SQL-Server, Oracle, DB2 et bien d'autres), vous pouvez simplement ajouter une CHECKcontrainte:

ALTER TABLE foo 
  ADD CONSTRAINT aa_cannot_be_equal_to_bb_CHK
    CHECK (aa <> bb) ;

Je ne vois aucun moyen d'avoir cela dans MySQL, en utilisant uniquement des contraintes référentielles. Outre les déclencheurs, vous pouvez autoriser les deux colonnes à avoir des valeurs égales et simplement ignorer les lignes en accédant toujours à la table via une vue:

CREATE VIEW foo_correct AS
SELECT id, aa, bb
FROM foo
WHERE aa <> bb ;

Vous pouvez également restreindre les opérations d'insertion et de mise à jour via des procédures (stockées) qui prennent en charge la contrainte et ne permettent pas d'insérer (ou de modifier) ​​des données qui ne la satisfont pas.

ypercubeᵀᴹ
la source
-1

Les deux colonnes en question font référence à la même table à barres. Pourriez-vous diviser la table Bar en deux afin qu'elles contiennent id avec les différents ensembles de valeurs?

msi77
la source
1
Alors, disons que nous avons trois couples dans le Footableau: (1,2) (2,3) (3,1). Comment diviser les trois valeurs?
ypercubeᵀᴹ
1
Je suis d'accord, suggestion erronée.
msi77