Обмеження таблиці 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
UNIQUE пропускає кому, перш ніж вона почнеться ..
Маджид Башир

Відповіді:


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
karmakaze

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; перша таблиця робить більше того, що я сподіваюсь на неї, зберігайте ПЕРШИЙ КЛЮЧ той самий ). Будьте в курсі цього ефекту.


1

Якщо у вас вже є таблиця і не можете / не хочете її відтворити з будь-якої причини, використовуйте індекси :

CREATE UNIQUE INDEX my_index ON my_table(col_1, col_2);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.