Possible options to get the expected results are:
JSON_MODIFY()
and SELECT
statement
JSON_MODIFY()
and dynamic statement
JSON_MODIFY()
and SELECT
statement:
As is mentioned in the documentation, in SQL Server 2017 (14.x) and in Azure SQL Database, you can provide a variable (or an expression in this case) as the value of path.
So you can easily build a path for each of the new key/value
pairs.
DECLARE @old varchar(1000) = '{"hello1":"1","hello2":"2","hello3":"3"}'
DECLARE @new varchar(1000) = '{"hello2":"a","hello3":"b"}'
SELECT @old = JSON_MODIFY(
@old,
CONCAT('$."', n.[key], '"'),
COALESCE(n.[value], o.[value])
)
FROM OPENJSON(@old) o
JOIN OPENJSON(@new) n ON n.[key] = o.[key]
JSON_MODIFY()
and dynamic statement:
The scenario is almost the same, but each update is in separate statement, generated dynamically:
DECLARE @old varchar(1000) = '{"hello1":"1","hello2":"2","hello3":"3"}'
DECLARE @new varchar(1000) = '{"hello2":"a","hello3":"b"}'
DECLARE @stm nvarchar(max)
SELECT @stm = STRING_AGG(
CONCAT(
'SELECT @old = JSON_MODIFY(@old, ''$."', n.[key], '"'', ''',
COALESCE(n.[value], o.[value]), ''')'
),
'; '
)
FROM OPENJSON(@old) o
JOIN OPENJSON(@new) n ON n.[key] = o.[key]
DECLARE @err int
EXEC @err = sp_executesql @stm, N'@old varchar(1000) OUTPUT', @old OUTPUT
IF @err = 0 PRINT 'Success' ELSE PRINT 'Error'
Result:
Both approaches return the following JSON:
{"hello1":"1","hello2":"a","hello3":"b"}
Adding new key\value
pair(s):
If the new JSON content inludes new key\value
pair(s), simply use FULL JOIN
:
DECLARE @old varchar(1000) = '{"hello1":"1","hello2":"2","hello3":"3"}'
DECLARE @new varchar(1000) = '{"hello2":"a","hello4":"b"}'
SELECT @old = JSON_MODIFY(
@old,
CONCAT('$."', n.[key], '"'),
COALESCE(n.[value], o.[value])
)
FROM OPENJSON(@old) o
FULL JOIN OPENJSON(@new) n ON n.[key] = o.[key]