Вот небольшой эксперимент, который я провел в базе данных Oracle (10g). Помимо удобства реализации (Oracle), я не могу понять, почему некоторые вставки принимаются, а другие отклоняются.
create table sandbox(a number(10,0), b number(10,0));
create unique index sandbox_idx on sandbox(a,b);
insert into sandbox values (1,1); -- accepted
insert into sandbox values (1,2); -- accepted
insert into sandbox values (1,1); -- rejected
insert into sandbox values (1,null); -- accepted
insert into sandbox values (2,null); -- accepted
insert into sandbox values (1,null); -- rejected
insert into sandbox values (null,1); -- accepted
insert into sandbox values (null,2); -- accepted
insert into sandbox values (null,1); -- rejected
insert into sandbox values (null,null); -- accepted
insert into sandbox values (null,null); -- accepted
Предполагая, что иногда имеет смысл иметь несколько строк с неизвестными значениями столбцов, я могу вспомнить два возможных варианта использования, связанных с предотвращением дублирования:
1. Я хочу отклонить дубликаты, но принимаю, когда значение какого-либо ограниченного столбца неизвестно.
2. Я хочу отклонить дубликаты даже в тех случаях, когда значение ограниченного столбца неизвестно.
Очевидно, Oracle реализует нечто иное:
3. Отклонить дубликаты, но принять (только), когда все значения столбцов с ограничениями неизвестны.
Я могу придумать, как использовать реализацию Oracle для использования case (2) - например, иметь специальное значение для «unknown» и сделать столбцы необнуляемыми. Но я не могу понять, как использовать case (1).
Другими словами, как я могу заставить Oracle работать так?
create table sandbox(a number(10,0), b number(10,0));
create unique index sandbox_idx on sandbox(a,b);
insert into sandbox values (1,1); -- accepted
insert into sandbox values (1,2); -- accepted
insert into sandbox values (1,1); -- rejected
insert into sandbox values (1,null); -- accepted
insert into sandbox values (2,null); -- accepted
insert into sandbox values (1,null); -- accepted
insert into sandbox values (null,1); -- accepted
insert into sandbox values (null,2); -- accepted
insert into sandbox values (null,1); -- accepted
insert into sandbox values (null,null); -- accepted
insert into sandbox values (null,null); -- accepted