2017-01-26 7 views
0

Возможно ли сделать XOR CHECK CONSTRAINT?Postgres SQL Exclusive OR (XOR) CHECK CONSTRAINT, возможно ли это?

Я делаю это на тестовой таблице, я только что сделал, что называется тест и имеет 3 колонки:

  • идентификатор, BigInt
  • а, BigInt
  • б, 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); 

Который должен потерпеть неудачу, видя, как он не принимает значение TRUE, по обе стороны от OR. Тем не менее, вставка очень хорошая.

Когда я смотрю на то, что Postgres на самом деле хранится в виде ограничения я получаю это:

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

Я слышал, и превалирует над ИЛИ, так что даже это должно работать.

У кого-нибудь есть решение для этого? Предпочтительно тот, который также возможен с тремя или более столбцами? Я понимаю, что это может быть сложнее.

EDIT: Изменение

= NULL 

в

IS NULL 

дать мне:

ERROR: cannot cast type boolean to bigint 
+3

Это 'IS NULL'. – jarlh

+0

@jarlh «ОШИБКА: не могу использовать тип boolean to bigint», если я это сделаю. – Blanen

+1

Кажется, что вы пытаетесь использовать какой-то специальный SQL-адрес Postgresql здесь (я не знаю.) – jarlh

ответ

2

Вы не можете сравнивать NULL значения с =, вам нужно IS NULL

(a IS NOT NULL AND b is NULL) OR (b IS NOT NULL AND a 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 = NULL и b = NULL бит был вопрос, как @a_horse_with_no_name указано. Вы могли бы также рассмотреть эту производную, которая не требует оператора OR:

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

Конечно, это работает исключительно только два столбца XOR сравнения. С тремя или более столбца 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) 
); 

 Смежные вопросы

  • Нет связанных вопросов^_^