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
独特之处是缺少一个逗号开始之前..
马吉德·巴希尔

Answers:


344

将UNIQUE声明放在列定义部分中;工作示例:

CREATE TABLE a (
    i INT,
    j INT,
    UNIQUE(i, j) ON CONFLICT REPLACE
);

6
好答案+1。此创建语法是否允许我使用常规的insert方法,而不使用带有SQLiteDatabase.CONFLICT_REPLACE标志的insertWithOnConflict?
Oleg Belousov 2014年

3
我正在使用ON CONFLICT IGNORE(还没有尝试过替换)超过2列的列,但是我没有看到它遵循唯一约束,只是很高兴地添加了重复项。
2014年

5
显然是因为我有NULL列,并且只拍摄了唯一的签出窗口
迈克尔·迈克尔(Michael Michael)

当心使用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

我最初是这样做的...没有用。我再次尝试过以防万一...仍然无法正常工作
Rich

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;第一个表正在执行我期望做的更多工作,保持主键不变) )。请注意这种影响。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.