Уникальный индекс на NULL поля в Postgres: подробное руководство
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Для того чтобы обеспечить условную уникальность для столбцов, которые могут включать NULL значения, вам нужно создать частичный индекс. Вот пример SQL-кода для PostgreSQL:
CREATE UNIQUE INDEX idx_uniq_conditional
ON YourTable (YourColumn)
WHERE YourColumn IS NOT NULL;
Данный индекс обеспечит уникальность в столбце YourColumn
для значений, отличных от NULL, и позволит включать сколько угодно строк с NULL значением в этом столбце.
Возможности PostgreSQL 15: Уникальность NULL
PostgreSQL 15 облегчает работу с уникальными ограничениями, применяемыми к NULL, благодаря новому условию NULLS NOT DISTINCT
. Таким образом, NULL теперь ведёт себя аналогично любому другому уникальному значению, что упрощает управление ограничениями:
ALTER TABLE your_table
ADD CONSTRAINT your_constraint UNIQUE NULLS NOT DISTINCT (column1, column2, ...);
На версиях PostgreSQL ниже 15-й необходимо использовать другие методы реализации подобного типа уникальности.
Стратегии для старых версий PostgreSQL
Функция COALESCE: Замещение NULL и обеспечение уникальности
Функцию COALESCE
можно применить как средство замены NULL
на уникальные значения:
CREATE UNIQUE INDEX idx_uniq_coalesce
ON your_table ((COALESCE(your_nullable_column, 'unique_placeholder')));
Рекомендуется использовать UUID в качестве заполнителя для предотвращения коллизий. Кроме того, рекомендуется включить ограничение CHECK
для предотвращения нежелательных вставок значения заполнителя.
Генератор: Создание индексов для производных столбцов
Вычисляемые столбцы позволяют создавать виртуальные столбцы, которые являются пригодными для индексации:
ALTER TABLE your_table
ADD your_generated_column AS (COALESCE(your_nullable_column, 'unique_placeholder'));
CREATE UNIQUE INDEX idx_uniq_generated
ON your_table (your_generated_column);
Таким образом, NULL значения преобразуются в уникальные значения для нужд индексации.
Частичный индекс с перекрытием
Когда требуется создать индекс для нескольких столбцов, которые могут содержать NULL, сложность увеличивается:
CREATE UNIQUE INDEX idx_uniq_partial
ON your_table (col1, col2)
WHERE col1 IS NOT NULL AND col2 IS NOT NULL;
Необходимо внимательно подходить к выбору стратегии и оценивать возможность убрать условие WHERE
для повышения эффективности работы баз данных.
Визуализация
Создание уникальных ограничений для столбцов, пропускающих NULL, можно сравнить с игрой в тетрис: необходимо формировать уникальные комбинации фигур, среди которых есть поражающиеся:
| Фигура A | Фигура B | Фигура C |
| -------- | -------- | ---------- |
| 🧩🔹 | 🧩🔹 | 🧩 (Пустота) |
| 🧩🔹 | 🧩 (Пустота) | 🧩🔹 |
| 🧩 (Пустота) | 🧩🔹 | 🧩🔹 |
Уникальное ограничение: В каждой строке уникальная комбинация пазлов без пропусков.
Правильно: 🧩🔹🧩🔹🧩 🧩🔹🧩 🧩🔹 🧩 🧩🔹🧩🔹
Неправильно: 🧩🔹🧩🔹🧩 🧩🔹🧩🔹🧩 // Повторение однотипного набора без пропусков
Это отлично иллюстрирует концепцию уникального ограничения SQL, при котором значения NULL игнорируются, позволяя остальным значениям уникально сочетаться.
Применение на практике
Удаление замещающих ключей: Последствия
При проектировании баз данных, замещающие ключи помогают связывать таблицы. Однако, когда уникальные ограничения применяются непосредственно к столбцам данных, важно осознавать последствия их удаления:
CREATE UNIQUE INDEX idx_uniq_user_recipe
ON menu(user_id, recipe_id)
WHERE MenuId IS NULL;
Возможно, для каждой комбинации пользователя и рецепта требуется всего одна запись, независимо от значения MenuId
.
Минимальные определения таблиц
Минимальные определения таблиц помогают прозрачно видеть структуру и предотвращают смешивание данных, поддерживая при этом уникальные ограничения. Лучше концентрироваться на предотвращении дублирования пар пользователь-рецепт, вне зависимости от MenuId
.
Внешние ключи: Острый двухсторонний меч
Использование внешних ключей обеспечивает целостность данных, однако их включение в уникальные ограничения требует балансировки, особенно при использовании частичных индексов.
Полезные материалы
- SQL UNIQUE Constraint — учебный курс W3Schools на тему уникальности в SQL.
- PostgreSQL: Documentation: 16: 11.8. Partial Indexes — руководство по условной уникальности от PostgreSQL.
- Создание индексов с фильтрацией – SQL Server | Microsoft Learn — инструкция Microsoft по созданию индексов с фильтрацией, в том числе и для
NULL
. - Как определить блокировку в SQL Server — описание индексации столбцов для уникальности на MSSQLTips.
- Stack Overflow: Уникальное ограничение на два столбца — обсуждение на Stack Overflow о уникальности для нескольких столбцов в MySQL и других системах.