12

I want to update an existing JSON value inside a JSON array. I can append a new JSON to the JSON array using JSON_MODIFY. Suppose i have a JSON like :

[{"id":"101","name":"John"}, {"id":"102","name":"peter"}]

But i want to update only the json with id=102.

Is it possible using JSON_MODIFY()?

EDIT:

Actual data

{"Details":{"SId":{"Type":"string","Value":"1234"},"BookList":{"Type":"List","Value":[{"id": "101", "name": "Book1"},{"id": "102", "name": "Book2"}]},"SName":{"Type":"string","Value":"john"}}}
1
  • 2
    Please do not ever edit question in a way that invalidates existing answers. If you need to add some details mark it clearly or ask new question Commented Apr 16, 2018 at 14:07

4 Answers 4

23

You could use CTE to parse it and combine path in UPDATE part:

WITH cte AS (
  SELECT *
  FROM t
  CROSS APPLY OPENJSON(c) s
  WHERE i = 1
    AND JSON_VALUE(s.value, '$.id')=102
)
UPDATE cte
SET c = JSON_MODIFY(c, '$[' + cte.[key] + '].name', 'Joe');

DBFiddle Demo

Output:

-- Before
[{"id":"101","name":"John"}, {"id":"102","name":"peter"}]

-- After
[{"id":"101","name":"John"}, {"id":"102","name":"Joe"}]

This will work on SQL Server 2017+ or SQL Azure DB otherwise you will get error. More info about path literal

Sign up to request clarification or add additional context in comments.

4 Comments

I have given my actual json format.How can i use cte and cross aply there?
Can you please suggest a solution that works in versions below SQL Server 2017? i'm getting The argument 2 of the "JSON_MODIFY" must be a string literal. error.
@Jishad, you could generate your update statements. Something like select 'update [yourtable] set [jsoncol] = json_modify([jsoncol], ''$[' + [key] + '].name'', ''Joe'') where id = ' + [yourtable].id from [yourtable] cross apply openjson([jsoncol]) and then execute them all with sp_executesql (of course, being wary of sql injection)
Wouldn't believe how hard I've hunted for this answer, much love
1

Updating JSON Data (Postgresql)

If the column in your table contains json data and you want to update this data, you can use the following structure:

UPDATE table_name SET column_name = '{"key" : value}'::jsonb 
WHERE column_name::jsonb @> '{“new_key” : new_value}'::jsonb;

Note: Usually @> is used as the "contains" operator.

Comments

0

The best way is to generate the statement like this:

  • In this way you, won't get the error of "Cannot resolve the collation conflict between Latin1_General_BIN and SQL_Latin1_General_CP1_CI_AS"
  • Also, you won't get this error "The argument 2 of the JSON_MODIFY must be a string literal"
    WITH cte AS (
      SELECT 
      t.PrimaryKey,
      JSON_VALUE([value], '$.id') as id,
      t.JsonColumn,
      o.*
      ,('UPDATE MyTable set JsonColumn = JSON_MODIFY(JsonColumn, ''$['+[key]+'].id'', ''NewVALUE'') WHERE PrimaryKey = '''+t.PrimaryKey COLLATE SQL_Latin1_General_CP1_CI_AS+ '''') as statement
      FROM MyTable t
       CROSS APPLY OPENJSON(JSON_QUERY(JsonColumn, '$')) o WHERE  JSON_VALUE(o.value, '$.Id')= 1
       )
    select * from cte; 
    

Comments

0

Do like this:

Declare @Input nvarchar(max) = N'[{"id":"101","name":"John"}, {"id":"102","name":"peter"}]';
Declare @UpdatedItem nvarchar(max) = N'{"id":"102","name":"peter1"}'

SET @Input = JSON_MODIFY(@Input, CONCAT('$[', (SELECT [Key] FROM OPENJSON(@Input) as I WHERE JSON_VALUE(I.Value,'$.id') = "102"), ']'), JSON_QUERY(@UpdatedItem));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.