Перейти к содержанию

Unique constraint

Unique Constraint на nullable полях в БД

Что будет, если в БД повесить на nullable поле БД констрейнт на уникальность и попытаться вставить несколько записей с null в этом поле?

По стандарту SQL null это не значение, это отсутствие значения. Поэтому с точки зрения БД (null = null) - fasle и (null <> null) - false и БД не считают, что несколько null в одной колонке нарушают констрейнт уникальности.

В принципе, большинство разработчиков это понимают. Интересно же то, что это верно не для всех БД. Например, MSSQL Server отходит от стандарта, и в случае с unique constraint считает null значением, и не дает вставить больше одной записи. Для того, чтобы воспроизвести поведение всех остальных БД на MSSQL необходимо воспользоваться дополнительным условием на индексе:

CREATE UNIQUE NONCLUSTERED INDEX idx_col1_notnull ON TBL(col1) WHERE col1 IS NOT NULL;

И то, эта конструкция появилась только с версии SQL Server 2008, до нее вам бы пришлось придумывать какие-нибудь костыли.

С составными индексами еще интереснее. Как поведет себя nullable поле в составном индексе?
Например, следующий код:

create table my_table (
    A int not null,
    B int not null,
    C int null,
    constraint u_constrainte unique (A, B, C)
);

insert into my_table (A, B, C) values (1, 2, 3);
insert into my_table (A, B, C) values (1, 2, null);
insert into my_table (A, B, C) values (1, 2, null);

Правильный ответ: зависит от БД. Стандарт SQL дает расплывчатую информацию, что будет в этом случае. На практике же, PostgreSQL без проблем выполнит все 3 insert. А Oracle на третьем insert будет жаловаться на нарушение констрейнта. При этом, если бы все 3 поля были nullable, то Oracle разрешил бы вставлять сколько угодно записей (null, null, null);