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

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

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

3 ответов


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


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

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

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

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

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

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

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

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

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


вы можете создать 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;

Если вы хотите, чтобы ваш уникальный индекс выдавал ошибку, когда две строки будут одинаковыми, если вы игнорируете нулевые столбцы (и не хотите использовать триггеры из ответа Satyam), вы можете сделать что-то вроде этого

CREATE TABLE `test` (
    `Field1`    INTEGER,
    `Field2`    INTEGER
);
CREATE UNIQUE INDEX `ix` ON `test` (
    `Field1`,
    `Field2`
);
INSERT INTO `test`(`Field1`,`Field2`) VALUES (1,NULL);
INSERT INTO `test`(`Field1`,`Field2`) VALUES (1,NULL); -- This shouldn't be allowed

DROP INDEX IF EXISTS `ix`;
CREATE UNIQUE INDEX `ix2` ON `test` (
    `Field1`,
    ifnull(`Field2`, 0)  --use this instead
); --will fail