更新SQL Server中的嵌套JSON值

更新SQL Server中的嵌套JSON值,json,sql-server,sql-update,sql-server-2017,Json,Sql Server,Sql Update,Sql Server 2017,我的表中有以下Json: { "filterCriteria":[ { "fieldId":"abc", "filterData":[ { "values":[ { "id":1, "value":"1", "tex

我的表中有以下Json:

{ 
   "filterCriteria":[ 
      { 
         "fieldId":"abc",
         "filterData":[ 
            { 
               "values":[ 
                  { 
                     "id":1,
                     "value":"1",
                     "text":"1"
                  },
                  { 
                     "id":2,
                     "value":"2",
                     "text":"2"
                  }
               ],
               "filterType":"equals"
            }
         ]
      },
      { 
         "fieldId":"def",
         "filterData":[ 
            { 
               "values":[ 
                  { 
                     "id":3,
                     "value":"3",
                     "text":"3"
                  },
                  { 
                     "id":4,
                     "value":"4",
                     "text":"4"
                  }
               ],
               "filterType":"equals"
            }
         ]
      }
   ]
}
我想根据特定字段Id的索引更新值节点

让我们举个例子:如果我想更新字段
id=“abc”
id=1
的值节点,那么我必须编写以下代码:

DECLARE @JSON nvarchar(max) = Above mentioned JSON

SELECT
    JSON_MODIFY(@JSON,'$."filterCriteria"[0].filterData[0].values[0].value', 'Hey');

但是,如果我必须根据某些过滤器上的索引获取进行更新,那么我就不知道如何进行更新。有人能帮我吗?

一种可能的方法是解析输入JSON,找到索引并修改JSON。请注意,您需要SQL Server 2017+在
JSON\u MODIFY()
调用中提供一个变量作为
path
的值:

JSON:

声明:

SELECT @json = JSON_MODIFY(
   @json,
   CONCAT('$."filterCriteria"[', id1, '].filterData[', id2, '].values[', id3, '].value'),
   'Hey'
)
FROM (
   SELECT j1.[key] AS id1, j3.[key] AS id2, j4.[key] AS id3
   FROM OPENJSON(@json, '$.filterCriteria') j1
   CROSS APPLY OPENJSON(j1.[value], '$') WITH (
      fieldId varchar(3) '$.fieldId',
      filterData nvarchar(max) '$.filterData' AS JSON
   ) j2
   CROSS APPLY OPENJSON(j2.filterData, '$') j3 
   CROSS APPLY OPENJSON (j3.[value], '$.values') j4
   CROSS APPLY OPENJSON (j3.[value], '$.values') WITH (
      id int '$.id'
   ) j5
   WHERE (j2.fieldId = 'abc') AND (j5.id = 1)
) t

SELECT @json
结果(基于您的示例JSON):


谢谢@Zhorov的回复,但我需要更新表中生成的json,filterdata可能有多个值。fieldId=“abc”,而不是id=“abc”我相信这就是你的意思
SELECT @json = JSON_MODIFY(
   @json,
   CONCAT('$."filterCriteria"[', id1, '].filterData[', id2, '].values[', id3, '].value'),
   'Hey'
)
FROM (
   SELECT j1.[key] AS id1, j3.[key] AS id2, j4.[key] AS id3
   FROM OPENJSON(@json, '$.filterCriteria') j1
   CROSS APPLY OPENJSON(j1.[value], '$') WITH (
      fieldId varchar(3) '$.fieldId',
      filterData nvarchar(max) '$.filterData' AS JSON
   ) j2
   CROSS APPLY OPENJSON(j2.filterData, '$') j3 
   CROSS APPLY OPENJSON (j3.[value], '$.values') j4
   CROSS APPLY OPENJSON (j3.[value], '$.values') WITH (
      id int '$.id'
   ) j5
   WHERE (j2.fieldId = 'abc') AND (j5.id = 1)
) t

SELECT @json
{ 
   "filterCriteria":[ 
      { 
         "fieldId":"abc",
         "filterData":[ 
            { 
               "values":[ 
                  { 
                     "id":1,
                     "value":"Hey",
                     "text":"1"
                  },
                  { 
                     "id":2,
                     "value":"2",
                     "text":"2"
                  }
               ],
               "filterType":"equals"
            }
         ]
      },
      { 
         "fieldId":"def",
         "filterData":[ 
            { 
               "values":[ 
                  { 
                     "id":3,
                     "value":"3",
                     "text":"3"
                  },
                  { 
                     "id":4,
                     "value":"4",
                     "text":"4"
                  }
               ],
               "filterType":"equals"
            }
         ]
      }
   ]
}