2017-01-26 16 views
0

XOR CHECK CONSTRAINTを作成することはできますか?Postgres SQL Exclusive OR(XOR)CHECK CONSTRAINT、それは可能ですか?

私はちょうどテストと呼ばれている作られた3列あり、テストテーブルの上にそれをやってる:

  • ID、BIGINT
  • 、BIGINT
  • B、BIGINT

私は、このためのチェック制約を作っ:

(a IS NOT NULL AND b = NULL) OR (b IS NOT NULL AND a = NULL) 

Which apparently would work in MSSQL

私はこれを行うことによってそれをテスト:

失敗する必要があり
INSERT INTO public.test(
    id, a, b) 
    VALUES (1, 1, 1); 

、それはORのいずれかの側にTRUEに評価されないと見て。 しかし、それはうまく挿入しています。

私が実際に制約として保存されたPostgresの何を見てみると、私はこの取得:

(a IS NOT NULL AND b = NULL::bigint OR b IS NOT NULL AND a = NULL::bigint) 

を私もこれはまだ動作するはずですので、聞いて、上の先例を取るOR。

誰にでも解決策がありますか? 3つ以上の列でも可能なものが望ましいでしょうか?私はそれらがより複雑かもしれないことを理解する。

EDIT:変更

= NULL 

IS NULL 

に私を与える:あなたは =とNULL値を比較することはできません

ERROR: cannot cast type boolean to bigint 
+3

「IS NULL」です。 – jarlh

+0

@jarlh "エラー:型booleanをbigintにキャストできません" – Blanen

+1

あなたは(ここではわからない)いくつかのPostgresql固有のSQLを使用しようとしているようです。 – jarlh

答えて

2

、あなたはIS NULL

が必要あなたは括弧で式全体を囲む必要があり、チェック制約のために

create table xor_test 
(
    id integer primary key, 
    a integer, 
    b integer, 
    check ((a IS NOT NULL AND b is NULL) OR (b IS NOT NULL AND a is NULL)) 
); 

-- works 
INSERT INTO xor_test(id, a, b) VALUES (1, null, 1); 

-- works 
INSERT INTO xor_test(id, a, b) VALUES (2, 1, null); 

-- failse 
INSERT INTO xor_test(id, a, b) VALUES (3, 1, 1); 
5

右@a_horse_with_no_nameが示されているように、a = NULLb = NULLビットが問題でした。

create table test 
(
    id integer primary key, 
    a integer, 
    b integer, 
    check ((a IS NULL) != (b IS NULL)) 
); 

もちろん、2つだけの列XOR比較して排他的に動作します:あなたはまた、ORオペレータを必要としないこの誘導体を考えるかもしれません。同様のテストテーブルで3つ以上の列XORを比較すると、次のような同様のアプローチに頼ることができます。

create table test 
(
    id integer primary key, 
    a integer, 
    b integer, 
    c integer, 
    check ((a IS NULL)::INTEGER + 
     (b IS NULL)::INTEGER + 
     (c IS NULL)::INTEGER = 1) 
); 
関連する問題