Sqlite NULL и уникальный?

Я заметил, что у меня могут быть значения NULL в столбцах с ограничением UNIQUE: UNIQUE(col)

Будет ли возникать проблема в определенных ситуациях?

Ответы

Ответ 1

В то время как следующие адреса имеют несколько нулевых значений, он не затрагивает никаких "проблем", связанных с таким дизайном, помимо возможной переносимости базы данных /SQL - как таковой, он, вероятно, не должен считаться ответом и оставлен здесь просто для справки.


Это действительно рассматривается в FAQ по SQLite. Это выбор дизайна. SQLite (в отличие от SQL Server) выбрал, что несколько значений NULL не учитывают уникальность в индексе.

В стандарте SQL требуется принудительное ограничение UNIQUE, даже если один или несколько столбцов в ограничении являются NULL, но SQLite этого не делает. Это не ошибка?

Возможно, вы ссылаетесь на следующий оператор SQL92:

  • Уникальное ограничение выполняется тогда и только тогда, когда две строки в таблице не имеют одинаковых ненулевых значений в уникальных столбцах.

Это утверждение неоднозначно, имея как минимум две возможные интерпретации:

  • Уникальное ограничение выполняется тогда и только тогда, когда две строки в таблице не имеют одинаковых значений и имеют непустые значения в уникальных столбцах.

  • Единственное ограничение выполняется тогда и только тогда, когда две строки в таблице не имеют одинаковых значений в подмножестве уникальных столбцов, которые не являются нулевыми.

SQLite следует интерпретации (1), как и PostgreSQL, MySQL, Oracle и Firebird. Верно, что Informix и Microsoft SQL Server используют интерпретацию (2), однако разработчики SQLite считают, что интерпретация (1) является наиболее естественным показанием этого требования, и мы также хотим максимизировать совместимость с другими механизмами СУБД SQL, а большинство других двигатели баз данных также идут с (1), так что это делает SQLite.

См. сравнение обработки NULL.

Ответ 2

Вы можете создать 2 триггера в таблице, чтобы проверить, существует ли строка с столбцом как null до любой операции вставки или обновления, если это вызывает исключение.

CREATE TRIGGER UniqueColumnCheckNullInsert
        BEFORE INSERT
        ON 'Tablename'
        WHEN NEW.'column_name' IS NULL
        BEGIN
        SELECT CASE WHEN((
            SELECT 1
            FROM 'Tablename'
            WHERE 'column_name' IS NULL
            )
            NOTNULL) THEN RAISE(ABORT, "error row exists") END;
    END;

CREATE TRIGGER UniqueColumnCheckNullUpdate
        BEFORE UPDATE
        ON 'Tablename'
        WHEN NEW.'column_name' IS NULL
        BEGIN
        SELECT CASE WHEN((
            SELECT 1
            FROM 'Tablename'
            WHERE 'column_name' IS NULL
            )
            NOTNULL) THEN RAISE(ABORT, "error row exists") END;
    END;