Kendala tabel SQLite - unik pada beberapa kolom

179

Saya dapat menemukan sintaks "grafik" di sini di situs web SQLite, tetapi tidak ada contoh dan kode saya mogok. Saya memiliki tabel lain dengan batasan unik pada satu kolom, tetapi saya ingin menambahkan batasan pada tabel pada dua kolom. Inilah yang saya miliki yang menyebabkan SQLiteException dengan pesan "kesalahan sintaks".

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

Saya melakukan ini berdasarkan hal berikut:

batasan meja

Agar lebih jelas, dokumentasi pada tautan yang saya berikan mengatakan bahwa CONTSTRAINT nameharus ada sebelum definisi kendala saya.

Namun, sesuatu yang dapat mengarah ke solusi adalah bahwa apa pun yang mengikuti definisi kolom kurung saya adalah apa yang dikeluhkan oleh debugger.

Jika saya taruh

...last_column_name last_col_datatype) CONSTRAINT ...

kesalahannya dekat "CONSTRAINT": kesalahan sintaks

Jika saya taruh

...last_column_name last_col_datatype) UNIQUE ...

kesalahannya dekat "UNIQUE": kesalahan sintaks

Kaya
sumber
1
UNIQUE kehilangan koma sebelum dimulai ..
Majid Bashir

Jawaban:

345

Masukkan deklarasi UNIK dalam bagian definisi kolom; contoh kerja:

CREATE TABLE a (
    i INT,
    j INT,
    UNIQUE(i, j) ON CONFLICT REPLACE
);
Ayman Hourieh
sumber
6
Jawaban bagus +1. Apakah ini membuat sintaks memungkinkan saya untuk menggunakan metode insert biasa, dan bukan insertWithOnConflict dengan flag SQLiteDatabase.CONFLICT_REPLACE?
Oleg Belousov
3
Saya menggunakan ON CONFLICT IGNORE(belum mencoba mengganti) dengan lebih dari 2 kolom, tapi saya tidak melihatnya menghormati batasan unik, itu hanya dengan riang menambahkan duplikat.
Michael
5
rupanya karena saya memiliki kolom NULL, dan itu hanya menembak unik memeriksa keluar jendela
Michael
Hati-hati menggunakannya ON CONFLICT REPLACEmungkin bukan yang Anda inginkan - menghapus baris yang sudah ada untuk memungkinkan baris baru dimasukkan. Biasanya, saya ingin ABORT atau ROLLBACK pelanggaran kendala. SQLite ON CONFLICT klausa
karmakaze
9

Nah, sintaks Anda tidak cocok dengan tautan yang Anda masukkan, yang menentukan:

 CREATE TABLE name (column defs) 
    CONSTRAINT constraint_name    -- This is new
    UNIQUE (col_name1, col_name2) ON CONFLICT REPLACE
Larry Lustig
sumber
Awalnya saya melakukan itu ... tidak berhasil. Saya mencobanya lagi untuk berjaga-jaga ... masih tidak berhasil
Kaya
1

Hati-hati bagaimana Anda mendefinisikan tabel karena Anda akan mendapatkan hasil berbeda saat disisipkan. Pertimbangkan yang berikut ini



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> 

Sementara efek sisipkan / perbarui adalah sama, idperubahan berdasarkan pada tipe definisi tabel (lihat tabel kedua di mana 'Alice' sekarang memiliki id = 4; tabel pertama melakukan lebih banyak dari apa yang saya harapkan untuk dilakukan, menjaga kunci PRIMER tetap sama. ). Waspadai efek ini.

punkish
sumber
1

Jika Anda sudah memiliki tabel dan tidak bisa / tidak ingin membuat ulang untuk alasan apa pun, gunakan indeks :

CREATE UNIQUE INDEX my_index ON my_table(col_1, col_2);
Oleg Yablokov
sumber