我无法弄清楚如何查询SQLite。 需要: 1)替换记录(主键),如果条件(新旧字段条目的比较) 2)如果主键上的数据库中不存在此类条目,则插入条目。
重要的是,它必须非常快速地工作! 我无法提出有效的询问。
编辑。
MyInsertRequest - 所需的表达式。
脚本:
CREATE TABLE testtable (a INT PRIMARY KEY, b INT, c INT)
INSERT INTO testtable VALUES (1, 2, 3)
select * from testtable
1|2|3
-- Adds an entry, because the primary key is not
++ MyInsertRequest VALUES (2, 2, 3) {if c>4 then replace}
select * from testtable
1|2|3
2|2|3
-- Adds
++ MyInsertRequest VALUES (3, 8, 3) {if c>4 then replace}
select * from testtable
1|2|3
2|2|3
3|8|3
-- Does nothing, because such a record (from primary key field 'a')
-- is in the database and none c>4
++ MyInsertRequest VALUES (1, 2, 3) {if c>4 then replace}
select * from testtable
1|2|3
2|2|3
3|8|3
-- Does nothing
++ MyInsertRequest VALUES (3, 34, 3) {if c>4 then replace}
select * from testtable
1|2|3
2|2|3
3|8|3
-- replace, because such a record (from primary key field 'a')
-- is in the database and c>2
++ MyInsertRequest VALUES (3, 34, 1) {if c>2 then replace}
select * from testtable
1|2|3
2|2|3
3|34|1
答案 0 :(得分:0)
不是INSERT OR REPLACE你需要什么?例如:
INSERT OR REPLACE INTO table (cola, colb) values (valuea, valueb)
发生UNIQUE约束违规时,使用REPLACE算法 删除导致约束违规的预先存在的行 在插入或更新当前行和命令之前 继续正常执行。
您必须将条件放在表上的唯一约束中。它会自动创建一个索引以使检查更有效。
e.g。
-- here the condition is on columnA, columnB
CREATE TABLE sometable (columnPK INT PRIMARY KEY,
columnA INT,
columnB INT,
columnC INT,
CONSTRAINT constname UNIQUE (columnA, columnB)
)
INSERT INTO sometable VALUES (1, 1, 1, 0);
INSERT INTO sometable VALUES (2, 1, 2, 0);
select * from sometable
1|1|1|0
2|1|2|0
-- insert a line with a new PK, but with existing values for (columnA, columnB)
-- the line with PK 2 will be replaced
INSERT OR REPLACE INTO sometable VALUES (12, 1, 2, 6)
select * from sometable
1|1|1|0
12|1|2|6
答案 1 :(得分:0)
假设您的要求是:
a
不存在时插入新行; a
且现有c
大于新c
时更换行; a
存在且现有c
小于或等于新c
时不执行任何操作; INSERT OR REPLACE
符合前两个要求。
对于最后一个要求,我知道使INSERT
无效的唯一方法是提供空行集。
像下面这样的SQLite命令可以完成这项任务:
INSERT OR REPLACE INTO sometable SELECT newdata.* FROM
(SELECT 3 AS a, 2 AS b, 1 AS c) AS newdata
LEFT JOIN sometable ON newdata.a=sometable.a
WHERE newdata.c<sometable.c OR sometable.a IS NULL;
新数据(此示例中为3,2,1
)为LEFT JOIN
en,包含当前表格数据。
然后WHERE
会在新c
不小于现有c
时“取消选择”该行,并在行为新时保留该行,即sometable.* IS NULL
。
答案 2 :(得分:0)
我尝试了其他人的答案,因为我也遇到了解决这个问题的方法。
这应该有效,但我不确定性能影响。我相信您可能需要将第一列作为主键唯一,否则每次只需插入一条新记录。
INSERT OR REPLACE INTO sometable
SELECT columnA, columnB, columnC FROM (
SELECT columnA, columnB, columnC, 1 AS tmp FROM sometable
WHERE sometable.columnA = 1 AND
sometable.columnB > 9
UNION
SELECT 1 AS columnA, 1 As columnB, 404 as columnC, 0 AS tmp)
ORDER BY tmp DESC
LIMIT 1
在这种情况下,执行一个虚拟查询并将其联合到第二个查询上,这将影响性能,具体取决于它的编写方式以及表的索引方式。下一个性能问题有可能导致结果有序且有限。但是,我希望第二个查询只返回一条记录,因此它不应该太过性能损失。
你也可以省略ORDER BY tmp LIMIT 1
并且它适用于我的sqlite版本,但它可能会影响性能,因为它最终可能会更新记录两次(如果适用,则写入原始值,然后写入新值)。 / p>
另一个问题是,即使条件声明它不应该更新,你也最终会对表进行写入。