SQLite'INSERT OR REPLACE INTO'行为不正确

时间:2016-04-17 18:34:19

标签: java mysql sqlite primary-key

我正在使用SQLite存储 id uuid 捕获的值。< / p>

我用这个命令创建表:

CREATE TABLE IF NOT EXISTS statz_fish_caught 
('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
 'uuid' TEXT NOT NULL,
 'value' INTEGER NOT NULL,
 'caught' TEXT NOT NULL);

我使用此命令插入(或替换)行:

INSERT OR REPLACE INTO statz_fish_caught (uuid,value,caught) 
VALUES ('uuid comes here', a number here, 'a certain string').

假设您在表格中有这些数据:

http://pasteboard.co/gofap3y.png

这些数据意味着UUID1共捕获了9条(1 + 5 + 3)鱼。鱼类1中有1种,2种鱼类中有5种,3种鱼类中有3种.UUID2仅捕获了10种鱼类型1的鱼类。现在让我们假设UUID1捕获一种新的鱼类型:鱼类型4.数据库应创建一个新行自动递增值为id 5, uuid 为'uuid1', value = 1且捕获 = fish type 4。

现在让我们假设UUID捕获另一条鱼类3的鱼。应该更新具有鱼类型3(它具有id 3)的uuid1行以表示值4,如下所示:

http://pasteboard.co/goBZatx.png

这是可能的,如果是的话,怎么样?

2 个答案:

答案 0 :(得分:1)

您正在使用INTEGER AUTOINCREMENT PRIMARY KEY,并且您的表中没有任何其他UNIQUE字段:这意味着现有行与您之间的行不可能发生冲突试图添加,因此不会有REPLACE

您应该像这样更改表格的定义:

CREATE TABLE IF NOT EXISTS statz_fish_caught 
('id' INTEGER PRIMARY KEY NOT NULL,
 'uuid' TEXT NOT NULL,
 'value' INTEGER NOT NULL,
 'caught' TEXT NOT NULL);

请注意,通过更改此项,您必须在添加行时手动设置id值,因为它不再由DBMS管理。

修改Here您可以找到一个有效的例子;注意主键的值是如何变化的。

编辑#2 :正如ishmaelMakitla所建议的,将UNIQUE字段放在UUID字段应该可以解决问题;我已相应更新了我的答案。

CREATE TABLE IF NOT EXISTS statz_fish_caught 
('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
 'uuid' TEXT NOT NULL UNIQUE,
 'value' INTEGER NOT NULL,
 'caught' TEXT NOT NULL);

警告:如SQLite文档中所述,

  

AUTOINCREMENT关键字会产生额外的CPU,内存,磁盘空间和磁盘I / O开销,如果不是严格需要,应该避免使用。通常不需要它。

另外,正如您在this示例中所看到的,已更新行的id已更改,这是我强烈建议避免的。

编辑#3 我花了一段时间,但this示例应该做你想要的。

您必须使用的查询是这样的(6是您要添加的捕获的鱼类):

INSERT OR REPLACE INTO statz_fish_caught (uuid,value,caught) 
VALUES (
     -- (select `id` from statz_fish_caught where uuid = 'uu1'),
     'uu1', 
     (select `value` from statz_fish_caught where uuid = 'uu1') + 6, 
     (select `caught` from  statz_fish_caught where uuid = 'uu1')
);

请注意,如果要保留更新行的id字段的当前值,则必须取消注释值的第一行,并在列列表中添加id字段声明。

答案 1 :(得分:0)

除了Cynical所说的,你应该将UUID设置为 UNIQUE - 这样,将替换具有匹配UUID的行。因此,表格应修改如下:

CREATE TABLE `statz_fish_caught` (
`id`    INTEGER NOT NULL,
`uuid`  TEXT NOT NULL UNIQUE,
`value` INTEGER NOT NULL,
`caught`    TEXT NOT NULL,
PRIMARY KEY(id)
);

我通过以下方式对此进行了测试:

INSERT OR REPLACE INTO statz_fish_caught 
(uuid,value,caught) VALUES (hex(randomblob(16)), 1, 'caught-1 ');

然后我执行了以下查询字符串(注意,我使用了十六进制生成的UUID(上一个查询中的randomblob(16))。所以运行:

INSERT OR REPLACE INTO statz_fish_caught (uuid,value,caught) VALUES ('uuid-of-row-to-update', 2, 'caught-1-updated');