Bac*_*Man 3 oracle constraints
我一直在努力解决这个检查约束几个小时,并希望有人能够解释为什么这个检查约束没有做我认为它应该做的事情.
ALTER TABLE CLIENTS
add CONSTRAINT CHK_DISABILITY_INCOME_TYPE_ID CHECK ((IS_DISABLED IS NULL AND DISABILITY_INCOME_TYPE_ID IS NULL) OR (IS_DISABLED = 0 AND DISABILITY_INCOME_TYPE_ID IS NULL) OR (IS_DISABLED = 1));
Run Code Online (Sandbox Code Playgroud)
基本上,您必须被禁用以收集残疾收入.看起来似乎(IS_DISABLED IS NULL AND DISABILITY_INCOME_TYPE_ID IS NULL)没有强制执行此检查约束的第一部分(见下文).
可用值为DISABILITY_INCOME_TYPE_ID1和2,通过外键强制执行.双方IS_DISABLED并DISABILITY_INCOME_TYPE_ID可以为空.
-- 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);
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助,迈克尔
虽然我没有Oracle,但我使用PostgreSQL和你的第一个例子(IS_DISABLED存在NULL并且DISABILITY_INCOME_TYPE_ID是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)
Run Code Online (Sandbox Code Playgroud)
在这里我们清楚地看到,在这种情况下,您的表达式(至少在PostgreSQL上)返回NULL.从手册,
[...]评估为TRUE或UNKNOWN的表达式成功.如果插入或更新操作的任何行产生FALSE结果,则会引发错误异常,并且插入或更新不会更改数据库.[...]
因此,如果Oracle的行为与PostgreSQL相同,则检查约束将通过.
要查看是否是这种情况,请通过明确检查它并查看它是否有效来避免NULL shenanigans:
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));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4408 次 |
| 最近记录: |