SQLite table constraint - unique on multiple columns
Be careful how you define the table for you will get different results on insert. Consider the following
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>
While the insert/update effect is the same, the id
changes based on the table definition type (see the second table where 'Alice' now has id = 4
; the first table is doing more of what I expect it to do, keep the PRIMARY KEY the same). Be aware of this effect.
Put the UNIQUE declaration within the column definition section; working example:
CREATE TABLE a (
i INT,
j INT,
UNIQUE(i, j) ON CONFLICT REPLACE
);
Well, your syntax doesn't match the link you included, which specifies:
CREATE TABLE name (column defs)
CONSTRAINT constraint_name -- This is new
UNIQUE (col_name1, col_name2) ON CONFLICT REPLACE
If you already have a table and can't/don't want to recreate it for whatever reason, use indexes:
CREATE UNIQUE INDEX my_index ON my_table(col_1, col_2);