使用 JSON1 在 SQLite 中更新 JSON
Updating JSON in SQLite with JSON1
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);
我正在使用此 table 来存储关键字搜索并记录在对象 locs
中启动搜索的位置。此数据库中的示例条目 table 如下所示
id:1,lang:1,kwd:'Whosebug',locs:'{"1":1,"2":1,"5":1}'
此处的位置对象属性是存储在别处的实际位置的索引。
现在想象一下下面的场景
从位置索引“2”开始搜索 Whosebug
。在这种情况下,我只想增加该索引处的值,以便在操作后相应的行读取
id:1,lang:1,kwd:'Whosebug',locs:'{"1":1,"2":2,"5" :1}'
从先前未知的位置索引“7”开始搜索 Whosebug
,在这种情况下,更新后的相应行必须读取
id:1,lang:1,kwd:'Whosebug',locs:'{"1":1,"2":1,"5":1,"7 ":1}'
我不清楚这是否真的可以做到。我尝试了一些类似
的方法
UPDATE keywords json_set(locs,'$.2','2') WHERE kwd = 'Whosebug';
给出了错误信息 error near json_set
。如果有人能告诉我 how/whether 这个 should/can 完成,我将非常感激。
我本可以删除这个问题,但考虑到 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
,因此我们执行 IFNULL
TEST
WHERE id =
位确保我们定位正确的行
现在我在 SQLite 中与 JSON1 合作了一段时间,我有一个提示可以与其他走同一条路的人分享。为了执行就地 JSON 操作,编写极其复杂且难以维护的 SQL 很容易浪费您的时间。考虑在内存表中使用 SQLite - CREATE TEMP TABLE...
来存储中间结果并改为编写一系列 SQL 语句。这使得代码更易于理解和维护。
没有必要创建如此复杂的 SQL 子查询。
下面的SQL可以解决您的需求。
UPDATE keywords
SET locs = json_set(locs,'$.7', IFNULL(json_extract(locs, '$.7'), 0) + 1)
WHERE kwd = 'Whosebug';
我知道这是旧的,但它就像搜索时的第一个 link,值得更好的解决方案。
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);
我正在使用此 table 来存储关键字搜索并记录在对象 locs
中启动搜索的位置。此数据库中的示例条目 table 如下所示
id:1,lang:1,kwd:'Whosebug',locs:'{"1":1,"2":1,"5":1}'
此处的位置对象属性是存储在别处的实际位置的索引。
现在想象一下下面的场景
从位置索引“2”开始搜索
Whosebug
。在这种情况下,我只想增加该索引处的值,以便在操作后相应的行读取id:1,lang:1,kwd:'Whosebug',locs:'{"1":1,"2":2,"5" :1}'
从先前未知的位置索引“7”开始搜索
Whosebug
,在这种情况下,更新后的相应行必须读取id:1,lang:1,kwd:'Whosebug',locs:'{"1":1,"2":1,"5":1,"7 ":1}'
我不清楚这是否真的可以做到。我尝试了一些类似
的方法UPDATE keywords json_set(locs,'$.2','2') WHERE kwd = 'Whosebug';
给出了错误信息 error near json_set
。如果有人能告诉我 how/whether 这个 should/can 完成,我将非常感激。
我本可以删除这个问题,但考虑到 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
,因此我们执行IFNULL
TEST WHERE id =
位确保我们定位正确的行
现在我在 SQLite 中与 JSON1 合作了一段时间,我有一个提示可以与其他走同一条路的人分享。为了执行就地 JSON 操作,编写极其复杂且难以维护的 SQL 很容易浪费您的时间。考虑在内存表中使用 SQLite - CREATE TEMP TABLE...
来存储中间结果并改为编写一系列 SQL 语句。这使得代码更易于理解和维护。
没有必要创建如此复杂的 SQL 子查询。
下面的SQL可以解决您的需求。
UPDATE keywords
SET locs = json_set(locs,'$.7', IFNULL(json_extract(locs, '$.7'), 0) + 1)
WHERE kwd = 'Whosebug';
我知道这是旧的,但它就像搜索时的第一个 link,值得更好的解决方案。