SQLite NULL и уникальный?
Я заметил, что я могу иметь нулевые значения в Столбцах, которые имеют уникальное ограничение:UNIQUE(col)
будет ли это порождать какие-либо проблемы в определенных ситуациях?
3 ответов
при следующих адресов множественные значения NULL, это не решить любые "проблемы", связанные с таким дизайном, кроме возможной переносимости базы данных/SQL - как таковой, вероятно, следует не считается ответом и оставляется здесь только для справки.
Это фактически охвачено в FAQ SQLite. Это выбор дизайна-SQLite (в отличие от SQL Server) выбрал, что несколько значений NULL не засчитываются уникальность в индексе.
возможно, вы имеете в виду следующее утверждение из SQL92:
- уникальное ограничение выполняется тогда и только тогда, когда никакие две строки в таблице не имеют одинаковых ненулевых значений в уникальных столбцах.
Это заявление неоднозначно, имея по крайней мере две возможные интерпретации:
уникальное ограничение выполняется тогда и только тогда, когда никакие две строки в таблице не имеют одинаковых значений и имеют ненулевые значения в уникальных столбцах.
уникальное ограничение выполняется тогда и только тогда, когда никакие две строки в таблице не имеют одинаковых значений в подмножестве уникальных столбцов, которые не являются 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