3

私はこのチェック制約に数時間苦労しており、誰かがこのチェック制約が私がすべきだと思うことをしていない理由を説明してくれることを望んでいました.

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));

基本的に、障害所得を徴収するには障害者である必要があります。このチェック制約の最初の部分が(IS_DISABLED IS NULL AND DISABILITY_INCOME_TYPE_ID IS NULL)適用されていないように見えます (以下を参照)。

に使用できる値DISABILITY_INCOME_TYPE_IDは 1 と 2 で、外部キーによって強制されます。との両方IS_DISABLEDDISABILITY_INCOME_TYPE_IDnull にすることができます。

-- 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);

助けてくれてありがとう、マイケル

4

4 に答える 4

5

私はOracleを持っていませんが、PostgreSQLとあなたの最初の例( IS_DISABLEDbeing NULLand DISABILITY_INCOME_TYPE_IDbeing 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)

ここで、この場合、(少なくとも PostgreSQL では) 式が NULL を返すことがはっきりとわかります。説明書より、

[...] TRUE または UNKNOWN と評価される式は成功します。挿入または更新操作のいずれかの行が FALSE の結果を生成すると、エラー例外が発生し、挿入または更新はデータベースを変更しません。[...]

したがって、Oracle が PostgreSQL と同じように動作する場合、チェック制約はパスします。

これが当てはまるかどうかを確認するには、明示的にチェックして NULL シェナニガンを回避し、それが機能するかどうかを確認します。

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));
于 2008-11-15T00:47:06.217 に答える
1

チェック条件でNVLを使用してみてください。

于 2008-11-14T21:28:57.630 に答える
1

複合チェックが機能しない理由はわかりませんが、これは機能します。

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)

よろしくK

于 2008-11-14T22:00:33.823 に答える
0

このソリューションは機能します。

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));
于 2008-11-15T07:57:52.107 に答える