6
votes

Mysql: contraignant un ensemble de colonnes afin qu'au moins un n'est pas nul

Je veux avoir une table SQL avec deux colonnes. L'une est une clé dans une autre table, l'autre détient un littéral à chaîne. L'idée est que les numéros de téléphone peuvent être entrées exactement (auquel cas l'ID dans la table du répertoire est utilisé) ou en tant que caractères génériques (dans lesquels le littéral de la chaîne est utilisé).

Cela signifie qu'une colonne de la table tiendra une valeur et l'autre tiendra une nulle.

est-il possible de contraindre une table de manière à ce qu'une colonne soit une valeur, et l'autre doit être nul? Si les deux colonnes sont nuls ou que les deux ont une valeur, la ligne est invalide.

J'ai un sentiment que MySQL ne peut pas faire cela (car il ne semble pas avoir une boîte à outils complète en matière de contraintes), mais cela ne pouvait pas nuire à demander.


1 commentaires

Cela peut aider (pas exactement le même si même): Stackoverflow.com/questions/4523351/...


4 Réponses :


4
votes

Je ne suis pas au courant d'un moyen d'appliquer une telle contrainte.

En tant que solution de contournement, vous pouvez envisager de disposer de deux colonnes différentes: Si vous avez une colonne pour les données contenant l'ID de répertoire ou le littéral de la chaîne, et une autre colonne pour le type de données - soit 'Exact' ou 'Wildcard' -, vous pouvez définir une contrainte non nulle aux deux colonnes. Un inconvénient évident est que vous ne pouvez plus avoir de contrainte FK à la table des répertoires.


1 commentaires

Je vais accepter cela, mais le design réel que je suis allé est quelque peu différent. J'ai ajouté un champ aimable qui peut être soit exact, soit de la carte générique, et le contenu du champ de clé pointera sur le répertoire ou une nouvelle table générique, en fonction de la valeur du type de type. Le type et la clé sont une clé unique composite, la clé peut donc contenir la même valeur deux fois (une fois pour une clé pour le répertoire téléphonique et une fois pour une clé pour les caractères génériques).



2
votes

Vous pouvez faire des déclencheurs à exécuter avant l'insertion, pour vérifier les valeurs et déterminer si l'insertion ou la mise à jour devrait se produire ou non. Un bon exemple pour créer des déclencheurs comme celui-ci peut être trouvé ici: https://dba.stackexchange.com/questions/43284/two-Nullable-Columns-one-required-a-have-value


0 commentaires

0
votes

Les déclencheurs suivants ont fonctionné pour moi:

CREATE TRIGGER tgr_OrgFeeOwnerInsert
    BEFORE INSERT
    ON OrganisationFee
    FOR EACH ROW
BEGIN
    IF (SELECT ((new.fieldA IS NULL) + (new.fieldB IS NULL) + (new.fieldC IS NULL)) <> 2)
    THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'my error message';
    END IF;
END;

CREATE TRIGGER tgr_OrgFeeOwnerUpdate
    BEFORE UPDATE
    ON OrganisationFee
    FOR EACH ROW
BEGIN
    IF (SELECT ((new.fieldA IS NULL) + (new.fieldB IS NULL) + (new.fieldC IS NULL)) <> 2)
    THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'my error message';
    END IF;
END;


2 commentaires

Si le deuxième déclencheur soit avant de mettre à jour ? Les deux déclencheurs me ressemblent, outre le nom attribué.


@shmulvad j'ai mis à jour ma réponse.



0
votes

depuis que généré par des colonnes code> est une chose, c'est possible.

CREATE TABLE `test_multiple_not_null` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  `idOne` int(11) DEFAULT NULL,
  `idTwo` int(11) DEFAULT NULL,
  `not_null_constrain` int(11) GENERATED ALWAYS AS (coalesce(`idOne`,`idTwo`)) VIRTUAL NOT NULL,
  PRIMARY KEY (`id`)
);


0 commentaires