mskuratowski
mskuratowski

Reputation: 4124

Update JSON using JSON_MODIFY

I store JSON data in SQL Server.

My table looks like:

Table name: JsonData

Columns: ID, Data

My JSON looks like:

{
    "data": [{
            "identifier": 1,
            "someData": {
                "sample1": "lorem 1",
                "sample2": "test 1"
            }
        },
        {
            "identifier": 2,
            "someData": {
                "sample1": "lorem 2",
                "sample2": "test 2"
            }
        },
        {
            "identifier": 3,
            "someData": {
                "sample1": "lorem 3",
                "sample2": "test 3"
            }
        }
    ]
}

I'd like to use JSON_MODIFY to update e.g sample1 for identifier 3. How can I access to sample1 and modify it?

Upvotes: 1

Views: 4296

Answers (1)

Zhorov
Zhorov

Reputation: 29943

Example:

Your JSON is an array of JSON objects, so you need an index to access each element. In this case, one possible approach is to use an expression as path parameter for JSON_MODIFY. Note, that this feature is available in SQL Server 2017 (14.x) and in Azure SQL Database. The JSON array is splitted into elements using OPENJSON with default schema and in this case the returned columns are key, value and type.

Basic example:

Statement:

DECLARE @json nvarchar(max) = N'{
    "data": [{
            "identifier": 1,
            "someData": {
                "sample1": "lorem 1",
                "sample2": "test 1"
            }
        },
        {
            "identifier": 2,
            "someData": {
                "sample1": "lorem 2",
                "sample2": "test 2"
            }
        },
        {
            "identifier": 3,
            "someData": {
                "sample1": "lorem 3",
                "sample2": "test 3"
            }
        }
    ]
}'

SELECT JSON_MODIFY(@json, '$.data[' + j.[key] + '].someData.sample1', N'NewValue') AS JsonData
FROM OPENJSON(@json, '$.data') j
WHERE JSON_VALUE([value], '$.identifier') = 3

Output:

----------------------------
JsonData
----------------------------
{
    "data": [{
            "identifier": 1,
            "someData": {
                "sample1": "lorem 1",
                "sample2": "test 1"
            }
        },
        {
            "identifier": 2,
            "someData": {
                "sample1": "lorem 2",
                "sample2": "test 2"
            }
        },
        {
            "identifier": 3,
            "someData": {
                "sample1": "NewValue",
                "sample2": "test 3"
            }
        }
    ]
}

Table example:

Table:

CREATE TABLE #Data (
  ID int,
  Data nvarchar(max)
)
INSERT INTO #Data
   (ID, Data)
VALUES
   (1, N'{
    "data": [{
            "identifier": 1,
            "someData": {
                "sample1": "lorem 1",
                "sample2": "test 1"
            }
        },
        {
            "identifier": 2,
            "someData": {
                "sample1": "lorem 2",
                "sample2": "test 2"
            }
        },
        {
            "identifier": 3,
            "someData": {
                "sample1": "lorem 3",
                "sample2": "test 3"
            }
        }
    ]
}'),
   (2, N'{
    "data": [{
            "identifier": 1,
            "someData": {
                "sample1": "lorem 1",
                "sample2": "test 1"
            }
        },
        {
            "identifier": 2,
            "someData": {
                "sample1": "lorem 2",
                "sample2": "test 2"
            }
        },
        {
            "identifier": 3,
            "someData": {
                "sample1": "lorem 3",
                "sample2": "test 3"
            }
        }
    ]
}')

Statement:

SELECT 
   d.ID, c.Data
FROM #Data d
CROSS APPLY (
   SELECT JSON_MODIFY(d.Data, N'$.data[' + CONVERT(nvarchar(max), j.[key] COLLATE Latin1_General_CI_AS) + N'].someData.sample1', N'NewValue') AS Data
   FROM OPENJSON(d.Data, '$.data') j
   WHERE JSON_VALUE([value], '$.identifier') = 3
) c

Notes:

The key column has a BIN2 collation, so you need to convert with collate option.

Upvotes: 3

Related Questions