插入或更新条目但在唯一约束违规时失败

时间:2016-01-22 10:31:34

标签: sqlite

想象一下这样的表:

+-----+-------+
| id  | value |
+-----+-------+ 
| id1 | val1  |
| id2 | val2  |
+-----+-------+

idPRIMARY KEYvalueUNIQUE约束。

我想要做的是使用基于其主键插入或更新条目的查询,但如果违反了唯一约束,将失败。

例如,如果我尝试插入id1, val2,我希望查询失败,而插入id1, val3应该更新第一行。

我在sqlite3中观察到的是,如果我使用INSERT OR REPLACE插入id1, val2,它将替换两个现有条目。我还看了一下sqlite的ON CONFLICT子句,但似乎没有办法区分UNIQUEPRIMARY KEY约束违规。

有没有办法用sqlite做这样的事情,还是有其他方法来处理这样的情况?

3 个答案:

答案 0 :(得分:0)

OR REPLACE子句使用任何唯一约束(包括主键约束)来检测冲突。

如果内置行为不符合您的要求,您必须自己动手:

c.execute("UPDATE MyTable SET val = ? WHERE id = ?;", [newValue, id])
if c.rowcount == 0:
    c.execute("INSERT INTO MyTable(val, id) VALUES (?, ?);", [newValue, id])

答案 1 :(得分:0)

您可以通过如下创建表来实现此目的:

CREATE TABLE test (
   id INTEGER, 
   value VARCHAR(32) UNIQUE ON CONFLICT FAIL, 
   PRIMARY KEY(Id) ON CONFLICT REPLACE
);

关键是要为不同的列定义不同的ON CONFLICT子句。在插入具有冲突PK的新记录时,PRIMARY KEY(Id) ON CONFLICT REPLACE将导致sqlite替换记录,而在插入value VARCHAR(32) UNIQUE ON CONFLICT FAIL违反value约束时,UNIQUE导致sqlite失败。

这将在插入具有相同主键的新记录时更新现有值,但 如果尝试插入具有不同主键和相同值的两条记录,则会失败。

例如

INSERT INTO test VALUES (1, "test");
INSERT INTO test VALUES (1, "update");

将导致

SELECT * FROM test;
1|update

但在新PK中插入相同的值

INSERT INTO test VALUES (2, "update");

将得到Error: UNIQUE constraint failed: test.value

答案 2 :(得分:-1)

Jan,希望这会对您有所帮助:https://www.sqlite.org/lang_conflict.html