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

Я могу найти "диаграммы" синтаксиса на сайте 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": синтаксическая ошибка


person Rich    schedule 23.04.2010    source источник
comment
В начале UNIQUE отсутствует запятая.   -  person Majid Bashir    schedule 29.11.2016


Ответы (4)


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

CREATE TABLE a (
    i INT,
    j INT,
    UNIQUE(i, j) ON CONFLICT REPLACE
);
person Ayman Hourieh    schedule 23.04.2010
comment
Хороший ответ +1. Позволяет ли этот синтаксис создания использовать обычный метод вставки, а не insertWithOnConflict с флагом SQLiteDatabase.CONFLICT_REPLACE? - person Oleg Belousov; 25.01.2014
comment
Я использую ON CONFLICT IGNORE (еще не пробовал заменить) с более чем двумя столбцами, но я не вижу, чтобы он соблюдал уникальное ограничение, он просто весело добавляет дубликаты. - person Michael; 17.07.2014
comment
по-видимому, потому что у меня есть столбцы NULL, и это просто снимает уникальную проверку в окне - person Michael; 17.07.2014
comment
Остерегайтесь использования ON CONFLICT REPLACE, это может быть не то, что вы хотите - он удаляет уже существующие строки, чтобы можно было вставить новую строку. Обычно я хочу ABORT или ROLLBACK нарушение ограничения. Предложение SQLite ON CONFLICT - person karmakaze; 23.02.2020
comment
Кажется, что добавление UNIQUE(i, j) к оператору create полностью игнорируется на android. Он создает таблицу, но оставляет ограничение UNIQUE. Я смог сделать это только с помощью индекса. - person gattsbr; 11.08.2020
comment
@gattsbr Кажется? Как вы обнаружили, что это игнорируют? - person Louis CAD; 01.02.2021
comment
@LouisCAD Я обнаружил, что его игнорируют, добавляя одни и те же данные дважды, т.е. не уникальные. Если я правильно помню, на ios он работал. однако использование индекса работало с обоими. Олег сработал у меня - person gattsbr; 01.02.2021

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

 CREATE TABLE name (column defs) 
    CONSTRAINT constraint_name    -- This is new
    UNIQUE (col_name1, col_name2) ON CONFLICT REPLACE
person Larry Lustig    schedule 23.04.2010
comment
Я изначально так сделал ... не сработало. Я попробовал еще раз на всякий случай ... все равно не работает - person Rich; 24.04.2010


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



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; первая таблица выполняет больше того, что я ожидал, оставьте ПЕРВИЧНЫЙ КЛЮЧ такой же). Помните об этом эффекте.

person punkish    schedule 16.06.2019