2017-07-17 1 views
1

J'ai une table sqlite dans laquelle les caractéristiques du produit sont spécifiées. Les caractéristiques, par ex. couleur, sont dans des colonnes booléennes. Les colonnes sont "1" ou "NULL". Certaines fonctionnalités sont exclusives. Puisque la structure de la table est fixe, j'ai essayé de créer un trigger qui déclenche une exception, qui ne fonctionne pas. Qu'est-ce que je fais mal?Sqlite: Déclenchez pour limiter le nombre de valeurs dans la rangée

Exemple:

CREATE TABLE productColor(
    productId INTEGER PRIMARY KEY, 
    isRed INTEGER, 
    isBlue INTEGER, 
    isYellow INTEGER, 
    isBrown INTEGER) 

Le produit ne peut avoir une couleur. Mon idée était de compter les colonnes dans lesquelles plus d'une couleur est spécifiée, c'est-à-dire moins de trois valeurs NULL. S'il y a au moins une telle ligne, le déclencheur s'attend à déclencher une exception. Voici à quoi ressemble mon déclencheur:

CREATE TRIGGER onlyOneColor 
    BEFORE INSERT ON productColor 
    WHEN 
     (SELECT COUNT (*) FROM 
     (SELECT ((CASE WHEN isBrown IS NULL THEN 1 ELSE 0 END) + 
     (CASE WHEN isRed IS NULL THEN 1 ELSE 0 END) + 
     (CASE WHEN isBlue IS NULL THEN 1 ELSE 0 END) + 
     (CASE WHEN isYellow IS NULL THEN 1 ELSE 0 END)) 
     AS sumOfNulls FROM productColor) WHERE sumOfNulls<3) 
    >=1 
    BEGIN 
    SELECT RAISE(FAIL, 'More then one color specified'); 
    END; 
+0

Quelle (s) rangée (s) voulez-vous vérifier? Celui à insérer, ou autre (s)? –

+0

Celui qui est inséré suffirait. Je suppose qu'un déclencheur mis en place comme décrit vérifie toutes les lignes, mais je voulais aborder un problème à la fois – Fab

Répondre

0

Vous n'avez pas besoin d'un déclencheur; cela peut être fait avec les contraintes de vérification:

CREATE TABLE productColor (
    productId INTEGER PRIMARY KEY, 
    isRed  INTEGER CHECK (isRed = 1 OR isRed IS NULL), 
    isBlue INTEGER CHECK (isBlue = 1 OR isBlue IS NULL), 
    isYellow INTEGER CHECK (isYellow = 1 OR isYellow IS NULL), 
    isBrown INTEGER CHECK (isBrown = 1 OR isBrown IS NULL), 
    CHECK (ifnull(isRed, 0) + ifnull(isBlue, 0) + 
      ifnull(isYellow, 0) + ifnull(isBrown, 0) <= 1) 
); 

Si vous avez enregistré toutes les valeurs 0 ou 1, ces contrôles seraient plus simples. (0 n'a pas besoin de plus d'espace de stockage que NULL.)


Si vous avez vraiment besoin d'un déclencheur, vous pouvez mettre les conditions inversées dans la clause WHEN. (Veuillez noter que les valeurs dans la ligne à insérer sont accessibles avec NEW.isRed etc.)

+0

La solution avec les contraintes de vérification fonctionne très bien, je n'ai pas travaillé sur la détente plus loin – Fab