Ограничение таблицы SQLite - уникально для нескольких столбцов

179

Я могу найти синтаксис "диаграммы" на этом сайте SQLite, но примеров нет, и мой код дает сбой. У меня есть другие таблицы с уникальными ограничениями на один столбец, но я хочу добавить ограничение на таблицу на два столбца. Это то, что у меня вызывает SQLiteException с сообщением «синтаксическая ошибка».

CREATE TABLE name (column defs) 
UNIQUE (col_name1, col_name2) ON CONFLICT REPLACE

Я делаю это на основании следующего:

Таблица-ограничение

Чтобы быть понятным, в документации по предоставленной мной ссылке написано, что она CONTSTRAINT nameдолжна предшествовать определению моего ограничения.

Что-то, что может привести к решению, состоит в том, что то, что следует за моими определениями столбцов в скобках, является тем, на что жалуется отладчик.

Если я поставлю

...last_column_name last_col_datatype) CONSTRAINT ...

ошибка рядом с "CONSTRAINT": синтаксическая ошибка

Если я поставлю

...last_column_name last_col_datatype) UNIQUE ...

ошибка рядом с "UNIQUE": синтаксическая ошибка

Богатый
источник
1
УНИКАЛЬНЫЙ пропускает запятую, прежде чем она начнется ..
Маджид Башир

Ответы:

345

Поместите объявление UNIQUE в раздел определения столбца; рабочий пример:

CREATE TABLE a (
    i INT,
    j INT,
    UNIQUE(i, j) ON CONFLICT REPLACE
);
Айман Хуриех
источник
6
Хороший ответ +1. Позволяет ли это создавать синтаксис использовать обычный метод вставки, а не insertWithOnConflict с флагом SQLiteDatabase.CONFLICT_REPLACE?
Олег Белоусов
3
Я использую ON CONFLICT IGNORE(еще не пробовал заменить) более чем с 2 столбцами, но я не вижу, чтобы он соблюдал уникальное ограничение, он просто весело добавляет дубликаты.
Майкл
5
очевидно, потому что у меня есть NULL столбцы, и это просто снимает уникальное окно проверки
Майкл
Остерегайтесь использовать ON CONFLICT REPLACEего, возможно, не то, что вам нужно - он удаляет уже существующие строки, чтобы можно было вставить новую строку. Обычно я хотел бы прервать или откатить нарушение ограничения. Предложение SQLite ON CONFLICT
Кармаказе
9

Ну, ваш синтаксис не соответствует ссылке, которую вы включили, которая указывает:

 CREATE TABLE name (column defs) 
    CONSTRAINT constraint_name    -- This is new
    UNIQUE (col_name1, col_name2) ON CONFLICT REPLACE
Ларри Люстиг
источник
Я изначально сделал это ... не сработало. Я попробовал это снова на всякий случай ... все еще не работает
Рич
1

Будьте внимательны при определении таблицы, так как при вставке вы получите разные результаты. Рассмотрим следующее



CREATE TABLE IF NOT EXISTS t1 (id INTEGER PRIMARY KEY, a TEXT UNIQUE, b TEXT);
INSERT INTO t1 (a, b) VALUES
    ('Alice', 'Some title'),
    ('Bob', 'Palindromic guy'),
    ('Charles', 'chucky cheese'),
    ('Alice', 'Some other title') 
    ON CONFLICT(a) DO UPDATE SET b=excluded.b;
CREATE TABLE IF NOT EXISTS t2 (id INTEGER PRIMARY KEY, a TEXT UNIQUE, b TEXT, UNIQUE(a) ON CONFLICT REPLACE);
INSERT INTO t2 (a, b) VALUES
    ('Alice', 'Some title'),
    ('Bob', 'Palindromic guy'),
    ('Charles', 'chucky cheese'),
    ('Alice', 'Some other title');

$ sqlite3 test.sqlite
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite> CREATE TABLE IF NOT EXISTS t1 (id INTEGER PRIMARY KEY, a TEXT UNIQUE, b TEXT);
sqlite> INSERT INTO t1 (a, b) VALUES
   ...>     ('Alice', 'Some title'),
   ...>     ('Bob', 'Palindromic guy'),
   ...>     ('Charles', 'chucky cheese'),
   ...>     ('Alice', 'Some other title') 
   ...>     ON CONFLICT(a) DO UPDATE SET b=excluded.b;
sqlite> CREATE TABLE IF NOT EXISTS t2 (id INTEGER PRIMARY KEY, a TEXT UNIQUE, b TEXT, UNIQUE(a) ON CONFLICT REPLACE);
sqlite> INSERT INTO t2 (a, b) VALUES
   ...>     ('Alice', 'Some title'),
   ...>     ('Bob', 'Palindromic guy'),
   ...>     ('Charles', 'chucky cheese'),
   ...>     ('Alice', 'Some other title');
sqlite> .mode col
sqlite> .headers on
sqlite> select * from t1;
id          a           b               
----------  ----------  ----------------
1           Alice       Some other title
2           Bob         Palindromic guy 
3           Charles     chucky cheese   
sqlite> select * from t2;
id          a           b              
----------  ----------  ---------------
2           Bob         Palindromic guy
3           Charles     chucky cheese  
4           Alice       Some other titl
sqlite> 

Хотя эффект вставки / обновления одинаков, idизменения основаны на типе определения таблицы (см. Вторую таблицу, в которой теперь есть «Алиса» id = 4; первая таблица делает больше того, что я ожидаю, оставьте PRIMARY KEY таким же ). Помните об этом эффекте.

хулиганское
источник
1

Если у вас уже есть таблица и вы не можете / не хотите ее воссоздать по какой-либо причине, используйте индексы :

CREATE UNIQUE INDEX my_index ON my_table(col_1, col_2);
Олег Яблоков
источник