powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / SQLite [игнор отключен] [закрыт для гостей] / Как создать уникальный ключ для нескольких колонок?
7 сообщений из 7, страница 1 из 1
Как создать уникальный ключ для нескольких колонок?
    #37259492
Vano-1981
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Допустим, есть таблица "peoples" с полями "name1", "name2", "name3".
Нужно создать заклинание уникальности по полям "name1", "name2", "name3".
Версия SQLite3: 3.7.4

Создаю таблицу:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
drop table if exists peoples;
create table peoples(
    id INTEGER 
        PRIMARY KEY ASC AUTOINCREMENT
    , name1 TEXT
        COLLATE NOCASE
    , name2 TEXT
        COLLATE NOCASE
    , name3 TEXT
        COLLATE NOCASE
    , UNIQUE (name1 COLLATE NOCASE ASC, name2 COLLATE NOCASE ASC, name3 COLLATE NOCASE ASC)
);

Заполняю значениями:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
insert into peoples(name1, name2, name3)values('1', '1', '1');
--insert into peoples(name1, name2, name3)values('1', '1', '1');-- При выполнении запроса произошла ошибка: columns name1, name2, name3 are not unique--

-- Следующие две строки не вызывают ошибки
insert into peoples(name1, name2, name3)values(null, '1', '1');
insert into peoples(name1, name2, name3)values(null, '1', '1');

-- Следующие две строки не вызывают ошибки
insert into peoples(name1, name2, name3)values('2', null, null);
insert into peoples(name1, name2, name3)values('2', null, null);

В результате получаю:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
ID:name1:name2:name3:
1	1	1	1
1	1	1	1
2	null	1	1
3	null	1	1
4	2	null	null
5	2	null	null


Видим, что уникальность не соблюдается строк, которые содержат NULL в ключевых полях.
Точно так же ведет себя составной PRIMARY KEY.

Это баг SQLite?
Как бороться с этой проблемой?
...
Рейтинг: 0 / 0
Как создать уникальный ключ для нескольких колонок?
    #37259942
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vano-1981Как бороться с этой проблемой?Объявлять not null для "уникальных" полей.

P.S. null ничему не равен. В том числе - другому null.
...
Рейтинг: 0 / 0
Как создать уникальный ключ для нескольких колонок?
    #37259977
Vano-1981
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. SidorovVano-1981Как бороться с этой проблемой?Объявлять not null для "уникальных" полей.

P.S. null ничему не равен. В том числе - другому null.

Такой вариант не подходит т.к. в моей БД значение поля может быть NULL.
Так потому что таблица содержит настройки для пользователей.
Еслли ссылка на пользователя не указана, значит настройка применяется для любого пользователя, у которого она не задана явно. Изначально настроечная БД наполнена дефолтными значениями. Пользователи заходят в систему, меняют настройки. В этот момент в конфиг-базу ложатся индивидуальные настройки.


Выше я привел простой пример с одной таблицей (чтобы форумчане не ломали голову).
Рабочая версия (незначительно упрощенная) выглядит так:

Создаем таблицы:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
/*Справочник пользователей системы.
login - логин пользователя (под которым пользователь заходил в основную систему).
*/
CREATE TABLE users ( 
    login TEXT 
        NOT NULL UNIQUE 
    , comment TEXT
    ,is_deleted BOOLEAN
        NOT NULL
        DEFAULT( 0 )
        CHECK (is_deleted in ( 0 ,  1 ))
);

/*Именованые данные пользователя.
Ключ=значение в разрезе пользователей.
Если пользователь не указан, значит значение действует для всех пользователей, у которых нет такого значения.
*/
CREATE TABLE named_values( 
    id_user TEXT 
        COLLATE NOCASE
        REFERENCES users(login) ON UPDATE CASCADE
    , id_key TEXT
        NOT NULL 
        COLLATE NOCASE
    , key_value TEXT 
    , PRIMARY KEY (id_user, id_key)
    --, UNIQUE (id_user COLLATE NOCASE ASC, id_key COLLATE NOCASE ASC)
);

Заполняем тестовыми данными:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
insert into named_values(id_user, id_key, key_value)values('ZVano', 'dbname', 'localhost:3329');
insert into named_values(id_user, id_key, key_value)values('ZVano', 'app-theme', 'Тема для ZVano');
insert into named_values(id_user, id_key, key_value)values(null, 'app-theme', 'default');
-- Тесты 
insert into named_values(id_user, id_key, key_value)values('ZVano', 'test', 'test3');
--Следующая строка вызовет ошибку ограничения уникальности
--insert into named_values(id_user, id_key, key_value)values('ZVano', 'tEsT', 'test4');

--Следующая строка НЕ вызовет ошибку ограничения уникальности, хотя должна
insert into named_values(id_user, id_key, key_value)values(null, 'test', 'test1.1');
insert into named_values(id_user, id_key, key_value)values(null, 'test', 'test1.2');
insert into named_values(id_user, id_key, key_value)values(null, 'tEsT', 'test2');
...
Рейтинг: 0 / 0
Как создать уникальный ключ для нескольких колонок?
    #37260072
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vano-1981--Следующая строка НЕ вызовет ошибку ограничения уникальности, хотя должна
insert into named_values(id_user, id_key, key_value)values(null, 'test', 'test1.1');
insert into named_values(id_user, id_key, key_value)values(null, 'test', 'test1.2');
insert into named_values(id_user, id_key, key_value)values(null, 'tEsT', 'test2');[/src]Ничего она (вам) не должна.
В SQL - троичная логика: да, нет и неизвестно.
Поэтому используйте null как "неизвестно", а не как "значение по умолчанию".
...
Рейтинг: 0 / 0
Как создать уникальный ключ для нескольких колонок?
    #37263457
Vano-1981
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. SidorovVano-1981--Следующая строка НЕ вызовет ошибку ограничения уникальности, хотя должна
insert into named_values(id_user, id_key, key_value)values(null, 'test', 'test1.1');
insert into named_values(id_user, id_key, key_value)values(null, 'test', 'test1.2');
insert into named_values(id_user, id_key, key_value)values(null, 'tEsT', 'test2');[/src]Ничего она (вам) не должна.
В SQL - троичная логика: да, нет и неизвестно.
Поэтому используйте null как "неизвестно", а не как "значение по умолчанию".

Блин... так и есть.
Что же делать?

В Firebird я бы переложил логику на триггер. Может и тут прокати...
Просьба кинуть ссылкой на мануал по синтаксису написания триггеров в SQLite. На любом языке, гланое - примеры.
...
Рейтинг: 0 / 0
Как создать уникальный ключ для нескольких колонок?
    #37263471
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vano-1981Что же делать?Определите значение "По умолчанию" как default и дело с концом :)
...
Рейтинг: 0 / 0
Как создать уникальный ключ для нескольких колонок?
    #37264186
Vano-1981
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. SidorovVano-1981Что же делать?Определите значение "По умолчанию" как default и дело с концом :)
Спасибо за помощь.

Попытаюсь сначала триггерами решить задачу.
Если не получится, тогда использую метод предложеный Вами.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / SQLite [игнор отключен] [закрыт для гостей] / Как создать уникальный ключ для нескольких колонок?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]