如何在 SQL 中替换 json 字符串中的数字数组?
Posted
技术标签:
【中文标题】如何在 SQL 中替换 json 字符串中的数字数组?【英文标题】:How can I go about replacing a number array inside a json string in SQL? 【发布时间】:2019-12-28 03:07:13 【问题描述】:SQL 中的数据在一个类似这样的单元格中包含一个很长的 JSON 字符串:
"Name": "Example",
"Results": [
"ResultId": 0,
"AnswerIds": "[1,2,33,4,5]"
,
"ResultId": 1,
"AnswerIds": "[2,3,4,55,6]"
]
我有一个替换 AnswerId 列表:将所有 2 替换为 7,将所有 3 替换为 8
我该如何为此编写脚本?
我可以使用 crossapply 和 JSON_Query 隔离 AnswerId,但不确定如何替换一个数组中的多个更改。
【问题讨论】:
对于基于 T-SQL 的解决方案,您可以从 Remove element from JSON array for whole table 获得想法。虽然该问题是关于删除数组成员的,但可以调整答案代码以更新数组成员。您可以使用Json_modify
一次更新整个数组 - 因此,要将所有 2 替换为 7,您必须编写类似 se @json = JSON_MODIFY(@json,'$.Results[0].AnswerIds',JSON_QUERY('[1,7,33,4,5]'))
的内容
虽然这可能可以使用 T-SQL 解决,但 Sylens 在他的回答中显示的 javascript 解决方案要简单得多,并且可能比您在 T-SQL 中开箱即用的任何东西都具有更好的性能.如果您不介意往返,我会双手采用 JavaScript 解决方案。
【参考方案1】:
const json =
"Name": "Example",
"Results": [
"ResultId": 0,
"AnswerIds": "[1,2,33,4,5]"
,
"ResultId": 1,
"AnswerIds": "[2,3,4,55,6]"
]
json.Results.forEach((itm, index)=>
const arr = JSON.parse(itm.AnswerIds);
const replacedArray = arr.map(num=>
if(num === 2) return 7;
if(num === 3) return 8;
return num;
);
json.Results[index].AnswerIds = JSON.stringify(replacedArray);
)
console.log(json);
这就是我所做的,获取 json.Results 数组并使用 forEach 循环对其进行迭代。
然后您可以访问每个结果的 AnswerIds 对象。
由于AnswerIds值是一个字符串,我们先将其转换为一个数组。
然后我们使用映射循环遍历该数组,并进行替换。
您可能想阅读 JS maps、JS foreach、JSON.parse、JSON.stringify强>
【讨论】:
【参考方案2】:SQL Server 2016 支持 JSON,但您没有指定 SQL 版本。 使用DelimitedSplit8k 你可以这样做:
-- SAMPLE STRING
DECLARE @string VARCHAR(1000) =
'
"Name": "Example",
"Results": [
"ResultId": 0,
"AnswerIds": "[1,2,33,4,5]"
,
"ResultId": 1,
"AnswerIds": "[2,3,4,55,6]"
]
';
-- SOLUTION
SELECT NewJSON =
(
SELECT
IIF(i.pos = 0,IIF(i.pos>0 AND sub.string IN(2,3), x.x, sub.string),
IIF(s2.ItemNumber=1,'"[','')+IIF(i.pos>0 AND sub.string IN(2,3),x.x,sub.string)) +
IIF(s2.ItemNumber>LEAD(s2.ItemNumber,1) OVER (ORDER BY s.ItemNumber,s2.ItemNumber),']"',
IIF(i.pos = 0,'',','))
FROM dbo.delimitedsplit8k(REPLACE(@string,CHAR(13),''),CHAR(10)) AS s
CROSS APPLY (VALUES(CHARINDEX('"AnswerIds": "',s.item))) AS i(pos)
CROSS APPLY (VALUES(SUBSTRING(s.item, i.pos+14, 8000))) AS ss(item)
CROSS APPLY dbo.delimitedsplit8k(ss.item,IIF(i.pos=0,CHAR(0),',')) AS s2
CROSS APPLY (VALUES(IIF(i.pos=0,s.item,
REPLACE(REPLACE(s2.item,']"',''),'[','')))) AS sub(string)
CROSS APPLY (VALUES(REPLACE(REPLACE(sub.string,'2',7),'3',8))) AS x(x)
ORDER BY s.ItemNumber, s2.ItemNumber
FOR XML PATH('')
);
返回:
"Name": "Example",
"Results": [
"ResultId": 0,
"AnswerIds": "[1,7,33,4,5]"
,
"ResultId": 1,
"AnswerIds": "[7,8,4,55,6]"
]
【讨论】:
以上是关于如何在 SQL 中替换 json 字符串中的数字数组?的主要内容,如果未能解决你的问题,请参考以下文章