← Назад к вопросам

Может ли unique key иметь значение null?

1.0 Junior🔥 221 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Может ли unique key иметь значение NULL?

Да, может! В большинстве СУБД (PostgreSQL, MySQL, SQL Server, Oracle, SQLite) UNIQUE constraint разрешает несколько NULL значений в одном столбце.

Почему NULL обходит UNIQUE?

В SQL стандарте NULL != NULL. Это логическое правило:

SELECT NULL = NULL;  -- Результат: NULL (не true!)
SELECT NULL IS NULL; -- Результат: true

Поэтому UNIQUE constraint работает так: "если значение NULL, пропусти проверку уникальности".

Пример проблемы

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE,
    phone VARCHAR(20) UNIQUE
);

-- Оба работают!
INSERT INTO users (email, phone) VALUES ('john@test.com', NULL);
INSERT INTO users (email, phone) VALUES ('jane@test.com', NULL);
-- Теперь в phone две NULL! Нарушена уникальность!

Решение 1: NOT NULL

CREATE TABLE users (
    email VARCHAR(255) UNIQUE NOT NULL,
    phone VARCHAR(20) UNIQUE NOT NULL
);
-- Теперь NULL невозможен

Решение 2: UNIQUE INDEX с WHERE (лучше)

-- PostgreSQL, MySQL 8.0+, SQL Server
CREATE UNIQUE INDEX idx_phone ON users(phone) 
WHERE phone IS NOT NULL;

Теперь:

  • phone может быть NULL несколько раз (не учитывается в индексе)
  • Если phone не NULL, он уникален

Решение 3: CHECK constraint

CREATE TABLE users (
    phone VARCHAR(20) UNIQUE,
    CHECK (phone IS NOT NULL)
);

Best Practices

  1. Если столбец должен быть уникальным → добавь NOT NULL
  2. Если столбец опционален → не используй UNIQUE
  3. Если нужна условная уникальность → используй UNIQUE INDEX с WHERE

Реальный пример правильного дизайна

CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,  -- Обязателен и уникален
    phone VARCHAR(20),                    -- Опционален
    social_id VARCHAR(100)                -- Опционален
);

CREATE UNIQUE INDEX idx_phone ON users(phone) 
    WHERE phone IS NOT NULL;
CREATE UNIQUE INDEX idx_social ON users(social_id) 
    WHERE social_id IS NOT NULL;

Вывод

UNIQUE constraint позволяет NULL из-за логики SQL (NULL != NULL). Это часто ошибка дизайна. Решение: используй NOT NULL для обязательных уникальных полей или UNIQUE INDEX с WHERE для опциональных.