2008-11-14 7 views
3

J'ai été aux prises avec cette contrainte de vérification pendant quelques heures et espérais que quelqu'un aurait la gentillesse d'expliquer pourquoi cette contrainte de vérification ne fait pas ce que je pense qu'elle devrait faire. Essentiellement, vous devez être invalide pour percevoir un revenu d'invalidité. Il semble que la première partie de cette contrainte de vérification (IS_DISABLED IS NULL AND DISABILITY_INCOME_TYPE_ID IS NULL) n'est pas appliquée (voir ci-dessous).Oracle Check Constraint

Les valeurs disponibles pour DISABILITY_INCOME_TYPE_ID sont 1 et 2, ce qui est appliqué via une clé étrangère. Les deux IS_DISABLED et DISABILITY_INCOME_TYPE_ID peuvent être null.

-- incorrectly succeeds (Why?) 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (null, 1); 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (null, 2); 

-- correctly fails 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (0, 1); 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (0, 2); 

-- correctly succeeds 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (0, null); 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (1, 1); 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (1, 2); 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (1, null); 
INSERT INTO CLIENTS (IS_DISABLED, DISABILITY_INCOME_TYPE_ID) VALUES (null, null); 

Merci pour votre aide, Michael

+0

Juste vérifier que je vois le même comportement que vous voyez sur Oracle 10.2.0.4.0. –

Répondre

5

Bien que je n'ai pas Oracle, je l'ai fait un test rapide avec PostgreSQL et votre premier exemple (IS_DISABLED étant NULL et DISABILITY_INCOME_TYPE_ID étant 1):

postgres=> select (null is null and 1 is null); 
?column? 
---------- 
f 
(1 registro) 

postgres=> select (null is null and 1 is null) or (null = 0 and 1 is null); 
?column? 
---------- 
f 
(1 registro) 

postgres=> select (null is null and 1 is null) or (null = 0 and 1 is null) or (null = 1); 
?column? 
---------- 

(1 registro) 

ici, nous voyons clairement que, dans thi s cas, votre expression (au moins sur PostgreSQL) renvoie NULL. De the manual,

[...] Les expressions évaluées à TRUE ou UNKNOWN réussissent. Si une ligne d'une opération d'insertion ou de mise à jour produit un résultat FALSE, une exception d'erreur est générée et l'insertion ou la mise à jour ne modifie pas la base de données. [...]

Donc, si Oracle se comporte comme PostgreSQL, la contrainte de vérification serait passe.

Pour voir si tel est le cas, éviter les manigances NULL en vérifiant explicily pour elle et voir si cela fonctionne:

CHECK ((IS_DISABLED IS NULL AND DISABILITY_INCOME_TYPE_ID IS NULL) 
    OR (IS_DISABLED IS NOT NULL AND IS_DISABLED = 0 AND DISABILITY_INCOME_TYPE_ID IS NULL) 
    OR (IS_DISABLED IS NOT NULL AND IS_DISABLED = 1)); 
+0

Je ne suis pas sûr que votre réponse soit encore correcte, mais votre explication m'a été très utile pour résoudre ce problème par moi-même. Pendant tout ce temps, j'étais évaluation null = 1 comme faux, alors qu'Oracle et Postgres évaluent cette expression comme inconnue. Différence majeure. – BacMan

1

Essayez d'utiliser NVL dans la condition de vérification.

1

Je ne sais pas pourquoi la vérification du composé ne fonctionne pas, mais cela fonctionne:

ALTER TABLE CLIENTS ADD CONSTRAINT CHK_1 CHECK (IS_DISABLED = 0 AND DISABILITY_INCOME_TYPE_ID IS NULL) 

ALTER TABLE CLIENTS ADD CONSTRAINT CHK_2 CHECK (IS_DISABLED IS NULL AND DISABILITY_INCOME_TYPE_ID IS NULL) 

ALTER TABLE CLIENTS ADD CONSTRAINT CHK_3 CHECK (IS_DISABLED = 1) 

Cordialement K

0

Cette solution fonctionne.

CHECK 
((IS_DISABLED IS NULL AND NVL(DISABILITY_INCOME_TYPE_ID, 0) = 0) 
OR (IS_DISABLED = 0 AND NVL(DISABILITY_INCOME_TYPE_ID, 0) = 0) 
OR (IS_DISABLED IS NOT NULL AND IS_DISABLED = 1));