SQLite插入和替换条件

时间:2013-08-29 08:15:13

标签: sqlite insert replace conditional-statements

我无法弄清楚如何查询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

3 个答案:

答案 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>

另一个问题是,即使条件声明它不应该更新,你也最终会对表进行写入。