moh*_*han 2 sql-server json spring-data-jpa json-query
我正在使用 mssql 并且一列有 json 数据,我想通过传递 id 来更新该 json 的那部分(数组)。
{
"customerName":"mohan",
"custId":"e35273d0-c002-11e9-8188-a1525f580dfd",
"feeds":[
{
"feedId":"57f221d0-c310-11e9-8af7-cf1cf42fc72e",
"feedName":"ccsdcdscsdc",
"format":"Excel",
"sources":[
{
"sourceId":69042417,
"name":"TV 2 Livsstil"
},
{
"sourceId":69042419,
"name":"Turk Max"
}
]
},
{
"feedId":"59bbd360-c312-11e9-8af7-cf1cf42fc72e",
"feedName":"dfgdfgdfgdfgsdfg",
"format":"XmlTV",
"sources":[
{
"sourceId":69042417,
"name":"TV 2 Livsstil"
},
{
"sourceId":69042419,
"name":"Turk Max"
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
假设如果我要通过customerId和feedId,它应该用我已经通过的提要更新整个提要。
我尝试使用以下查询,但没有帮助。
UPDATE
ExtractsConfiguration.dbo.Customers
SET
configJSON = JSON_MODIFY(configJSON,'$.feeds[]',{"feedName":"ccsdcdscsdc"})
WHERE
CustomerId = '9ee07040-c001-11e9-b29a-55eb3439cd7c'
AND json_query(configJSON,'$.feeds[].feedId'='57f221d0-c310-11e9-8af7-cf1cf42fc72e');
Run Code Online (Sandbox Code Playgroud)
@mohan,这是一个棘手的问题,我把它当作对自己的挑战。有一种方法可以像您所要求的那样更新嵌套 JSON 对象的值,但是,它并不像看起来那么简单。
由于您正在数组中工作,因此需要数组的索引才能更新嵌套值。在您的情况下,您不知道数组中的索引,但是,您确实有一个可以引用的键值,在本例中为您的feedName。
为了更新您的值,您首先需要“解压”您的 JSON,以便您可以在示例中过滤特定的 feedName“ccsdcdscsdc”。
这是一个可以在 SSMS 中运行的示例,它将帮助您朝着正确的方向前进。
我创建的第一件事是 @Customers TABLE 变量来模仿您在示例中显示的数据结构并插入示例数据。
DECLARE @Customers TABLE ( CustomerId VARCHAR(50), configJSON VARCHAR(MAX) );
INSERT INTO @Customers ( CustomerID, configJSON ) VALUES ( '9ee07040-c001-11e9-b29a-55eb3439cd7c', '{"customerName":"mohan","custId":"e35273d0-c002-11e9-8188-a1525f580dfd","feeds":[{"feedId":"57f221d0-c310-11e9-8af7-cf1cf42fc72e","feedName":"ccsdcdscsdc","format":"Excel","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]},{"feedId":"59bbd360-c312-11e9-8af7-cf1cf42fc72e","feedName":"dfgdfgdfgdfgsdfg","format":"XmlTV","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]}]}' );
Run Code Online (Sandbox Code Playgroud)
针对 @Customers 运行 SELECT 将返回以下内容:
+--------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| CustomerId | configJSON |
+--------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 9ee07040-c001-11e9-b29a-55eb3439cd7c | {"customerName":"mohan","custId":"e35273d0-c002-11e9-8188-a1525f580dfd","feeds":[{"feedId":"57f221d0-c310-11e9-8af7-cf1cf42fc72e","feedName":"ccsdcdscsdc","format":"Excel","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]},{"feedId":"59bbd360-c312-11e9-8af7-cf1cf42fc72e","feedName":"dfgdfgdfgdfgsdfg","format":"XmlTV","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]}]} |
+--------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
接下来,我匹配了您的更新规则:更新仅限于特定 CustomerId (9ee07040-c001-11e9-b29a-55eb3439cd7c) 和 feedName (ccsdcdscsdc) 的嵌套 JSON 值。
就像我提到的,我们需要首先“解压”JSON,因为我们不知道应该更新的特定键(索引)值。完成这两项任务(解包/更新)的最简单方法是使用公共表表达式 (CTE)。
所以,我是这样做的:
;WITH Config_CTE AS (
SELECT * FROM @Customers AS Customer
CROSS APPLY OPENJSON( configJSON, '$.feeds' ) AS Config
WHERE
Customer.CustomerId = '9ee07040-c001-11e9-b29a-55eb3439cd7c'
AND JSON_VALUE( Config.value, '$.feedName' ) = 'ccsdcdscsdc'
)
UPDATE Config_CTE
SET configJSON = JSON_MODIFY( configJSON, '$.feeds[' + Config_CTE.[key] + '].format', 'MS Excel' );
Run Code Online (Sandbox Code Playgroud)
CTE 允许我们“解压”(我编了这个词,因为它看起来很合适)configJSON中包含的 JSON,然后它允许我们对feedName应用过滤器。
AND JSON_VALUE( Config.value, '$.feedName' ) = 'ccsdcdscsdc'
Run Code Online (Sandbox Code Playgroud)
您还会注意到,我们包含了 CustomerId 规则:
Customer.CustomerId = '9ee07040-c001-11e9-b29a-55eb3439cd7c'
Run Code Online (Sandbox Code Playgroud)
CustomerId和feedName都可以很容易地成为 SQL 变量。
那么,这是做什么的呢?如果我们查看 Configs_CTE 结果集(通过将 UPDATE... 更改为 SELECT * FROM Config_CTE ),我们会看到:
+--------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+
| CustomerId | configJSON | key | value | type |
+--------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+
| 9ee07040-c001-11e9-b29a-55eb3439cd7c | {"customerName":"mohan","custId":"e35273d0-c002-11e9-8188-a1525f580dfd","feeds":[{"feedId":"57f221d0-c310-11e9-8af7-cf1cf42fc72e","feedName":"ccsdcdscsdc","format":"Excel","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]},{"feedId":"59bbd360-c312-11e9-8af7-cf1cf42fc72e","feedName":"dfgdfgdfgdfgsdfg","format":"XmlTV","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]}]} | 0 | {"feedId":"57f221d0-c310-11e9-8af7-cf1cf42fc72e","feedName":"ccsdcdscsdc","format":"Excel","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]} | 5 |
+--------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+
Run Code Online (Sandbox Code Playgroud)
这里有很多信息,但我们真正关心的是“key”列,因为它包含我们要更新的 feed 索引(在本例中为 0 )。
这样,就能够完成 feedName 为“ccsdcdscsdc”的“feed”的请求和从“Excel”到“MS Excel”的更新格式。
这家伙(注意 Config_CTE.[key] 的使用):
UPDATE Config_CTE
SET configJSON = JSON_MODIFY( configJSON, '$.feeds[' + Config_CTE.[key] + '].format', 'MS Excel' );
Run Code Online (Sandbox Code Playgroud)
有效吗?让我们看看更新后的表的数据。
+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| CustomerId | configJSON |
+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 9ee07040-c001-11e9-b29a-55eb3439cd7c | {"customerName":"mohan","custId":"e35273d0-c002-11e9-8188-a1525f580dfd","feeds":[{"feedId":"57f221d0-c310-11e9-8af7-cf1cf42fc72e","feedName":"ccsdcdscsdc","format":"MS Excel","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]},{"feedId":"59bbd360-c312-11e9-8af7-cf1cf42fc72e","feedName":"dfgdfgdfgdfgsdfg","format":"XmlTV","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]}]} |
+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
这是更新后的 JSON“美化”(很确定这不是我编造的)。
{
"customerName": "mohan",
"custId": "e35273d0-c002-11e9-8188-a1525f580dfd",
"feeds": [{
"feedId": "57f221d0-c310-11e9-8af7-cf1cf42fc72e",
"feedName": "ccsdcdscsdc",
"format": "MS Excel",
"sources": [{
"sourceId": 69042417,
"name": "TV 2 Livsstil"
}, {
"sourceId": 69042419,
"name": "Turk Max"
}]
}, {
"feedId": "59bbd360-c312-11e9-8af7-cf1cf42fc72e",
"feedName": "dfgdfgdfgdfgsdfg",
"format": "XmlTV",
"sources": [{
"sourceId": 69042417,
"name": "TV 2 Livsstil"
}, {
"sourceId": 69042419,
"name": "Turk Max"
}]
}]
}
Run Code Online (Sandbox Code Playgroud)
好了,你已经知道了,feedName “ccsdcdscsdc”的格式已从“Excel”更新为“MS Excel”。我不清楚您要更新的内容,因此我使用格式进行测试/示例。
我希望这能让您在任务中朝着正确的方向前进。快乐编码!
以下是可以在 SSMS 中运行的完整示例:
-- CREATE A CUSTOMERS TABLE TO MIMIC SCHEMA --
DECLARE @Customers TABLE ( CustomerId VARCHAR(50), configJSON VARCHAR(MAX) );
INSERT INTO @Customers ( CustomerID, configJSON ) VALUES ( '9ee07040-c001-11e9-b29a-55eb3439cd7c', '{"customerName":"mohan","custId":"e35273d0-c002-11e9-8188-a1525f580dfd","feeds":[{"feedId":"57f221d0-c310-11e9-8af7-cf1cf42fc72e","feedName":"ccsdcdscsdc","format":"Excel","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]},{"feedId":"59bbd360-c312-11e9-8af7-cf1cf42fc72e","feedName":"dfgdfgdfgdfgsdfg","format":"XmlTV","sources":[{"sourceId":69042417,"name":"TV 2 Livsstil"},{"sourceId":69042419,"name":"Turk Max"}]}]}' );
-- SHOW CURRENT DATA --
SELECT * FROM @Customers;
-- UPDATE "format" FROM "Excel" to "MS Excel" FOR feedName: ccsdcdscsdc --
WITH Config_CTE AS (
SELECT * FROM @Customers AS Customer
CROSS APPLY OPENJSON( configJSON, '$.feeds' ) AS Config
WHERE
Customer.CustomerId = '9ee07040-c001-11e9-b29a-55eb3439cd7c'
AND JSON_VALUE( Config.value, '$.feedName' ) = 'ccsdcdscsdc'
)
UPDATE Config_CTE
SET configJSON = JSON_MODIFY( configJSON, '$.feeds[' + Config_CTE.[key] + '].format', 'MS Excel' );
-- SHOW UPDATED DATA --
SELECT * FROM @Customers;
Run Code Online (Sandbox Code Playgroud)
编辑:
我想用给定的 feedId 更新整个新 feed
要将一个“提要”替换为全新的提要,您可以执行以下操作:
-- REPLACE AN ENTIRE JSON ARRAY OBJECT --
DECLARE @MyNewJson NVARCHAR(MAX) = '{"feedId": "this_is_an_entirely_new_node","feedName": "ccsdcdscsdc","format": "NewFormat","sources": [{"sourceId": 1,"name": "New Source 1"},{"sourceId": 2,"name": "New Source 2"}]}';
WITH Config_CTE AS (
SELECT * FROM @Customers AS Customer
CROSS APPLY OPENJSON( configJSON, '$.feeds' ) AS Config
WHERE
Customer.CustomerId = '9ee07040-c001-11e9-b29a-55eb3439cd7c'
AND JSON_VALUE( Config.value, '$.feedName' ) = 'ccsdcdscsdc'
)
UPDATE Config_CTE
SET configJSON = JSON_MODIFY( configJSON, '$.feeds[' + Config_CTE.[key] + ']', JSON_QUERY( @MyNewJson ) );
Run Code Online (Sandbox Code Playgroud)
运行此命令后,提要现在显示为:
{
"customerName": "mohan",
"custId": "e35273d0-c002-11e9-8188-a1525f580dfd",
"feeds": [
{
"feedId": "this_is_an_entirely_new_node",
"feedName": "ccsdcdscsdc",
"format": "NewFormat",
"sources": [
{
"sourceId": 1,
"name": "New Source 1"
},
{
"sourceId": 2,
"name": "New Source 2"
}
]
},
{
"feedId": "59bbd360-c312-11e9-8af7-cf1cf42fc72e",
"feedName": "dfgdfgdfgdfgsdfg",
"format": "XmlTV",
"sources": [
{
"sourceId": 69042417,
"name": "TV 2 Livsstil"
},
{
"sourceId": 69042419,
"name": "Turk Max"
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
JSON_QUERY( @MyNewJson )请注意UPDATE 中的使用。这个很重要。
来自微软的文档:
没有可选第二个参数的 JSON_QUERY 仅返回第一个参数作为结果。由于 JSON_QUERY 始终返回有效的 JSON,因此 FOR JSON 知道该结果不必转义。
如果您要在没有 JSON_QUERY 的情况下传递@MyNewJson,您的新 json 将被转义(例如,“customerName”变为“customerName”),就像它被存储为纯文本一样。JSON_QUERY 将返回未转义的有效 JSON,这在您的情况下是必需的。
另请注意,我为替换整个提要与单个项目值所做的唯一更改是切换
'$.feeds[' + Config_CTE.[key] + '].format'
Run Code Online (Sandbox Code Playgroud)
到
'$.feeds[' + Config_CTE.[key] + ']'.
Run Code Online (Sandbox Code Playgroud)