У меня есть таблица, подобная следующей:
create table my_table (
id int8 not null,
id_A int8 not null,
id_B int8 not null,
id_C int8 null,
constraint pk_my_table primary key (id),
constraint u_constrainte unique (id_A, id_B, id_C)
);
И я хочу (id_A, id_B, id_C)
быть отличным в любой ситуации. Поэтому следующие две вставки должны привести к ошибке:
INSERT INTO my_table VALUES (1, 1, 2, NULL);
INSERT INTO my_table VALUES (2, 1, 2, NULL);
Но он не работает должным образом, потому что согласно документации два NULL
значения не сравниваются друг с другом, поэтому обе вставки проходят без ошибок.
Как я могу гарантировать свое уникальное ограничение, даже если id_C
может быть NULL
в этом случае? На самом деле, реальный вопрос заключается в следующем: могу ли я гарантировать такую уникальность в «чистом sql» или мне нужно реализовать ее на более высоком уровне (в моем случае java)?
postgresql
constraint
null
unique-constraint
Мануэль Ледук
источник
источник
(1,2,1)
и(1,2,2)
в(A,B,C)
столбцах. Должно ли(1,2,NULL)
быть разрешено добавить или нет?Ответы:
Вы можете сделать это в чистом SQL . Создайте частичный уникальный индекс в дополнение к тому, который у вас есть:
Таким образом, вы можете ввести для
(a, b, c)
в вашей таблице:Но ни один из них во второй раз.
Или используйте два частичных
UNIQUE
индекса и не полный индекс (или ограничение). Лучшее решение зависит от деталей ваших требований. Для сравнения:Хотя это элегантно эффективно для одного столбца с нулем в
UNIQUE
индексе, он быстро выходит из-под контроля. Обсуждаем это - и как использовать UPSERT с частичными индексами:Asides
Нельзя использовать идентификаторы смешанного регистра без двойных кавычек в PostgreSQL.
Вы можете рассматривать
serial
столбец как первичный ключ илиIDENTITY
столбец в Postgres 10 или более поздней версии. Связанный:Так:
Если вы не ожидаете более 2 миллиардов строк (> 2147483647) за время жизни вашей таблицы (включая пустые и удаленные строки), рассмотрите
integer
(4 байта) вместоbigint
(8 байтов).источник
У меня была та же проблема, и я нашел другой способ добавить уникальный NULL в таблицу.
В моем случае поле
foreign_key_field
является положительным целым числом и никогда не будет равно -1.Таким образом, чтобы ответить на руководство Leduc, другое решение может быть
Я предполагаю, что идентификаторы не будут -1.
В чем преимущество создания частичного индекса?
В случае, если у вас нет предложения NOT NULL
id_a
,id_b
и выid_c
можете быть NULL вместе только один раз.С частичным индексом 3 поля могут быть NULL более одного раза.
источник
COALESCE
может быть эффективным для ограничения дубликатов, но индекс не будет очень полезен при запросах, поскольку это индекс выражения, который, вероятно, не будет соответствовать выражениям запроса. То есть, если быSELECT COALESCE(col, -1) ...
вы не попали в указатель.Нулевое значение может означать, что значение неизвестно для этой строки в данный момент, но будет добавлено, когда станет известно, в будущем (например,
FinishDate
для бегаProject
) или что никакое значение не может быть применено для этой строки (например,EscapeVelocity
для черной дырыStar
).На мой взгляд, обычно лучше нормализовать таблицы, исключив все нули.
В вашем случае вы хотите разрешить
NULLs
в своей колонке, но вы хотите, чтобы только одинNULL
был разрешен. Почему? Какие отношения это между двумя таблицами?Возможно, вы можете просто изменить столбец
NOT NULL
и сохранить вместоNULL
него специальное значение (например-1
), которое, как известно, никогда не появляется. Это решит проблему ограничения уникальности (но может иметь и другие, возможно, нежелательные побочные эффекты. Например, использование-1
в значении «неизвестно / не применимо» приведет к искажению любых сумм или усредненных вычислений в столбце. учитывать специальное значение и игнорировать его.)источник