Предикат, который вам нужно проверить:
if (col1 is not null and col2 is not null) then specific is not null
Предикат if A then B
можно записать как not A or B
Обратите внимание, что приоритет равен (not A) or B
см. Обсуждение здесь
Таким образом, вы получаете:
alter table spec add constraint my_spec
check (not (col1 is not null and col2 is not null) or specific is not null);
, если col1 или col2 равны нулю, spcific обнуляется
insert into spec(col1,col2,specific) values(null,null,null);
insert into spec(col1,col2,specific) values(1,null,null);
insert into spec(col1,col2,specific) values(null,1,null);
, если и col1, и col2 определены как секретныев NOT NULL
insert into spec(col1,col2,specific) values(1,1,1);
insert into spec(col1,col2,specific) values(1,1,null);
-- ORA-02290: check constraint (REPORTER.MY_SPEC) violated
В существующую таблицу вы можете добавить это check
, только если существующие данные полностью заполнят проверку, в противном случае вы получите это исключение
ORA-02293: cannot validate (OWNER.MY_SPEC) - check constraint violated
Чтобы найти строки, которыенарушил новое правило, просто запрос
select * from spec
where NOT (not (col1 is not null and col2 is not null) or specific is not null);
Вы должны либо удалить эти строки, либо установить specific
в ненулевое значение, либо установить col1 или col2 в NULL.
В качестве альтернативы Вы можете активировать ограничение с помощью опции NOVALIDATE
, это допускает существующие нарушения, но обеспечивает, чтобы новые изменения следовали ограничению.
alter table spec add constraint my_spec
check (not (col1 is not null and col2 is not null) or specific is not null)
enable novalidate;