jsonsqlitesql-updatesqlite-json1

Updating JSON in SQLite with JSON1


The SQLite JSON1 extension has some really neat capabilities. However, I have not been able to figure out how I can update or insert individual JSON attribute values.

Here is an example

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

I am using this table to store keyword searches and recording the locations from which the search was ininitated in the object locs. A sample entry in this database table would be like the one shown below

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

The location object attributes here are indices to the actual locations stored elsewhere.

Now imagine the following scenarios

It is not clear to me that this can in fact be done. I tried something along the lines of

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

which gave the error message error near json_set. I'd be most obliged to anyone who might be able to tell me how/whether this should/can be done.


Solution

  • I could have just deleted this question but given that the SQLite JSON1 extension appears to be relatively poorly understood I felt it would be more useful to provide an answer here for the benefit of others. What I have set out to do here is possible but the SQL syntax is rather more convoluted.

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

    will accomplish both of the updates I have described in my original question above. Given how complicated this looks a few explanations are in order


    Having now worked with JSON1 in SQLite for a while I have a tip to share with others going down the same road. It is easy to waste your time writing extremely convoluted and hard to maintain SQL in an effort to perform in-place JSON manipulation. Consider using SQLite in memory tables - CREATE TEMP TABLE... to store intermediate results and write a sequence of SQL statements instead. This makes the code a whole lot eaiser to understand and to maintain.