索引是否在json数组中有任何插入或更新值。 我有一个包含这些值的列:
["qwe","123"]
我希望在中间插入新值:
["qwe","asd","123"]
或删除一个:
["123"]
如何使用JSON_MODIFY
完成?
我只设法附加最后一个值:
select JSON_MODIFY([Column], 'append $', '')
from MyTable
或更新将中间值更改为null:
select JSON_MODIFY([Column], '$[1]', NULL)
from MyTable
然后将其更换为空。
答案 0 :(得分:2)
如果要在最后一个值之前插入新值,可以将最后一个值再次追加为n+1
,然后替换n
值:
DECLARE @Data TABLE
(
[ID] INT
,[Column] NVARCHAR(MAX)
);
INSERT INTO @Data ([ID], [Column])
VALUES (1, '["qwe","123"]');
SELECT JSON_MODIFY(JSON_MODIFY([Column], 'append $', JSON_VALUE([Column], '$[1]')), '$[1]', 'asd')
FROM @Data
WHERE [ID] = 1;
现在,如果我们有很多元素,并且如果我们想在第二个或第三个索引上插入新元素,上面的代码将不起作用,因为我们需要在新的元素之后交换所有值。
为此,我们可以使用OPNEJSON
函数拆分值,然后使用适当的索引插入新值,并使用FOR XML
或SRING AGGREGATE
函数连接值。
DECLARE @Data TABLE
(
[ID] INT
,[Column] NVARCHAR(MAX)
);
INSERT INTO @Data ([ID], [Column])
VALUES (2, '["qwe","123", "125" ,"126"]');
SELECT
'[' +
STUFF
(
(
SELECT ',' + [value] AS [value]
FROM
(
SELECT JS.[value]
,JS.[key] * 1.0
FROM @Data DS
CROSS APPLY OPENJSON([Column]) JS
WHERE DS.[ID] = 2
UNION ALL
SELECT 'asd'
,0.1
) DS ([value], [key])
ORDER BY [key]
FOR XML PATH, TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
)
+']';
答案 1 :(得分:1)
我认为没有正常的做法。
我发现只有以下方法如何做到
-- create and fill #TestData
SELECT '["qwe","asd","123"]' json_str
INTO #TestData
UNION ALL
SELECT '["zxc","asd","321"]'
UNION ALL
SELECT '[]'
UNION ALL
SELECT '["qwe","asd","12\"3"]' -- escaped quotes
UNION ALL
SELECT '["qwe","asd","<123>"]' -- special characters
-- delete demo
SELECT
json_str,
JSON_QUERY(CONCAT('[',STUFF((
SELECT CONCAT(',"',REPLACE([value],'"','\"'),'"')
FROM OPENJSON(json_str, '$')
WHERE [key]<>1 -- exclude element with index 1
ORDER BY [key]
FOR XML PATH('')),1,1,''),']')) new_json_str
FROM #TestData
-- insert demo
SELECT
json_str,
JSON_QUERY(CONCAT('[',STUFF((
SELECT CONCAT(',"',REPLACE([value],'"','\"'),'"')
FROM
(
SELECT 1 RowPriority,[key],[value]
FROM OPENJSON(json_str, '$')
UNION ALL
SELECT
2 RowPriority,
0, -- add after key with index 0
'new value' -- value
) q
ORDER BY [key],RowPriority -- sort values
FOR XML PATH('')),1,1,''),']')) new_json_str
FROM #TestData
DROP TABLE #TestData
还有一个例子,用于删除另一个条件的值并插入多个值
-- create and fill #TestData
SELECT '["qwe","asd","123"]' json_str
INTO #TestData
UNION ALL
SELECT '["zxc","asd","321"]'
UNION ALL
SELECT '[]' -- empty array
UNION ALL
SELECT '["qwe","asd","12\"3"]' -- escaped quotes
UNION ALL
SELECT '["qwe","asd","<123>"]' -- special characters
-- delete with another condition demo
SELECT
json_str,
JSON_QUERY(CONCAT('[',STUFF((
SELECT CONCAT(',"',REPLACE([value],'"','\"'),'"')
FROM OPENJSON(json_str, '$')
WHERE [value] NOT IN('qwe','123') -- another delete condition
ORDER BY [key]
FOR XML PATH('')),1,1,''),']')) new_json_str
FROM #TestData
-- insert several values demo
SELECT
json_str,
JSON_QUERY(CONCAT('[',STUFF((
SELECT CONCAT(',"',REPLACE([value],'"','\"'),'"')
FROM
(
SELECT 1 RowPriority,0 NewValOrder,[key],[value]
FROM OPENJSON(json_str, '$')
UNION ALL
SELECT 2 RowPriority,NewValOrder,AfterPosition,[value]
FROM (VALUES(0,1,'new value 1'),(0,2,'new value 2')) v(AfterPosition,NewValOrder,[value])
) q
ORDER BY [key],RowPriority,NewValOrder -- sort values
FOR XML PATH('')),1,1,''),']')) new_json_str
FROM #TestData
DROP TABLE #TestData
希望这个变体适合你。
STRING_AGG
代替FOR XML PATH('')
-- create and fill #TestData
SELECT '["qwe","asd","123"]' json_str
INTO #TestData
UNION ALL
SELECT '["zxc","asd","321"]'
UNION ALL
SELECT '[]' -- empty array
UNION ALL
SELECT '["qwe","asd","12\"3"]' -- escaped quotes
UNION ALL
SELECT '["qwe","asd","<123>"]' -- special characters
-- delete with another condition demo
SELECT
json_str,
JSON_QUERY(CONCAT('[',
(
SELECT STRING_AGG(CONCAT('"',REPLACE([value],'"','\"'),'"'),',') WITHIN GROUP(ORDER BY [key])
FROM OPENJSON(json_str, '$')
WHERE [value] NOT IN('qwe','123') -- another delete condition
),']')) new_json_str
FROM #TestData
-- insert several values demo
SELECT
json_str,
JSON_QUERY(CONCAT('[',
(
SELECT STRING_AGG(CONCAT('"',REPLACE([value],'"','\"'),'"'),',') WITHIN GROUP(ORDER BY [key],RowPriority,NewValOrder)
FROM
(
SELECT 1 RowPriority,0 NewValOrder,[key],[value]
FROM OPENJSON(json_str, '$')
UNION ALL
SELECT 2 RowPriority,NewValOrder,AfterPosition,[value]
FROM (VALUES(0,1,'new value 1'),(0,2,'new value 2')) v(AfterPosition,NewValOrder,[value])
) q
),']')) new_json_str
FROM #TestData
DROP TABLE #TestData
也许最后一个变体会更好,因为构造FOR XML PATH('')
会替换一些特殊字符(例如:<
- <
)。