【问题标题】:SQLite Insert and Replace with conditionSQLite 插入并替换为条件
【发布时间】:2013-08-29 08:15:13
【问题描述】:

我不知道如何查询 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

【问题讨论】:

  • 如果最后我想添加VALUES (1, 2, 1)怎么办?我看不懂标准!是不是:添加新的a,当a匹配并且new.c小于old.c时替换,否则什么都不做?

标签: sqlite insert replace conditional-statements


【解决方案1】:

INSERT OR REPLACE 不是你需要的吗?例如:

INSERT OR REPLACE INTO table (cola, colb) values (valuea, valueb)

当 UNIQUE 约束违反发生时,REPLACE 算法 删除导致违反约束的预先存在的行 在插入或更新当前行和命令之前 继续正常执行。

您必须将条件放在表的唯一约束中。它会自动创建一个索引来提高检查效率。

例如

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

【讨论】:

  • 替换的必要条件,WHERE 子句不适用于 INSERT OR REPLACE,可能是某种不同的设置条件......我看了它从来没有发现,我对 SQL 没有太多经验。跨度>
  • 添加了一个例子,条件在表上,不在查询中。这是我能想到的 SQLite 的唯一解决方案。
  • 好的,我认为您需要的是正确的MERGE 声明。据我所知,SQLite 不存在。我可能应该删除答案,因为它不相关,对不起
【解决方案2】:

假设您的要求是:

  • 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 JOINen 与当前表数据。

然后WHERE 将在新的c 不小于现有c 时“取消选择”该行,当行是新的时保留它,即sometable.* IS NULL

【讨论】:

  • 奇怪的是,这似乎比直接 INSERT OR REPLACE... 快 40% - 知道为什么会这样吗?
【解决方案3】:

我尝试了其他答案,因为我也遇到了这个问题的解决方案。

这应该可行,但是我不确定性能影响。我相信您可能需要第一列作为主键是唯一的,否则它每次都会简单地插入一条新记录。

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 版本,但它可能会影响性能,因为它最终会更新记录两次(写入原始值,然后写入新值,如果适用)。

另一个问题是,即使条件表明不应更新,您最终还是会写入表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-21
    相关资源
    最近更新 更多