3

SQLite JSON1 扩展有一些非常简洁的功能。但是,我无法弄清楚如何更新或插入单个 JSON 属性值。

这是一个例子

CREATE TABLE keywords
(
 id INTEGER PRIMARY KEY,
 lang INTEGER NOT NULL,
 kwd TEXT NOT NULL,
 locs TEXT NOT NULL DEFAULT '{}'
);

CREATE INDEX  kwd ON keywords(lang,kwd);

我正在使用此表来存储关键字搜索并记录在对象中发起搜索的位置locs。此数据库表中的示例条目如下所示

 id:1,lang:1,kwd:'stackoverflow',locs:'{"1":1,"2":1,"5":1}'

这里的位置对象属性是存储在别处的实际位置的索引。

现在想象以下场景

  • stackoverflow从位置索引“2”开始搜索。在这种情况下,我只想增加该索引处的值,以便在操作后读取相应的行

    id:1,lang:1,kwd:'stackoverflow',locs:'{"1":1,"2": 2 ,"5":1}'

  • 从以前未知的位置索引“7”开始搜索,stackoverflow在这种情况下,更新后的相应行必须读取

    id:1,lang:1,kwd:'stackoverflow',locs:'{"1":1,"2":1,"5":1, "7":1 }'

我不清楚这实际上是否可以做到。我尝试了一些类似的东西

UPDATE keywords json_set(locs,'$.2','2') WHERE kwd = 'stackoverflow';

这给出了错误消息error near json_set。对于任何能够告诉我如何/是否应该/可以完成的人,我将非常感激。

4

2 回答 2

4

没有必要使用子查询创建如此复杂的 SQL 来执行此操作。

下面的 SQL 将解决您的需求。

UPDATE keywords 
SET locs = json_set(locs,'$.7', IFNULL(json_extract(locs, '$.7'), 0) + 1) 
WHERE kwd = 'stackoverflow';

我知道这是旧的,但它就像搜索时的第一个链接,值得更好的解决方案。

于 2021-06-03T13:45:33.633 回答
3

我本可以删除这个问题,但鉴于 SQLite JSON1 扩展似乎对它的理解相对较少,我觉得为了他人的利益在这里提供答案会更有用。我在这里打算做的事情是可能的,但 SQL 语法相当复杂。

 UPDATE keywords set  locs = 
 (select json_set(json(keywords.locs),'$.**N**', 
 ifnull(
 (select json_extract(keywords.locs,'$.**N**') from keywords where id = '1'),
 0) 
 + 1) 
 from keywords where id = '1') 
 where id = '1';

将完成我在上面的原始问题中描述的两个更新。鉴于这看起来很复杂,有一些解释是有序的

  • UPDATE keywords部分进行实际更新,但它需要知道要更新什么
  • SELECT json_set部分是我们建立要更新的值的地方
  • 如果相关值首先不存在,我们不想+ 1对空值执行 a ,因此我们执行IFNULLTEST
  • 这些WHERE id =位确保我们瞄准正确的行

现在在 SQLite 中使用 JSON1 已经有一段时间了,我有一个技巧可以与其他走在同一条路上的人分享。编写极其复​​杂且难以维护的 SQL 以执行就地 JSON 操作很容易浪费您的时间。考虑在内存表中使用 SQLite -CREATE TEMP TABLE...来存储中间结果并改为编写一系列 SQL 语句。这使得代码更容易理解和维护。

于 2018-04-16T12:09:20.307 回答