我试图弄清楚如何修改存储在表(SQL SERVER)列中的json。
仅在与特定字符串匹配时,我才希望删除JSON的属性。
想象一下,我们在表中有一条记录,其中的JSON位于名为“ profile”(nvarchar(max))的列中:
{
name: "goofy",
class_cod_x: "1345",
}
然后另一条记录显示此JSON:
{
name: "donald",
class_cod_y: "1457",
}
现在,我们要搜索和更新记录内的所有JSON,其中包含startsWith“ class_cod”的属性。
我想从该列中删除所有的“ class_cod ..”属性。
我可以想象这样的查询:
UPDATE myTable SET profile = JSON_MODIFY( profile , "startsWith(class_cod)" , null)
这可能吗?在那种情况下,哪种是正确的语法?预先感谢!
UPDATE预期输出:
{
name: "goofy",
}
和
{
name: "donald",
}
“ class_cod”字段已完全删除。
一种方法是创建动态更新语句并手动运行生成的更新查询。像这样的东西。
SELECT 'UPDATE MYTABLE SET PROFILE=JSON_MODIFY(profile ,''$.' +x.[key]+ ''', null)'
FROM MYTABLE T
CROSS APPLY OPENJSON (profile, '$') x
WHERE x.[key] LIKE '%class_cod%'
此查询将创建如下的更新语句列表。
UPDATE MYTABLE SET PROFILE=JSON_MODIFY(profile ,'$.class_cod_x', null)
UPDATE MYTABLE SET PROFILE=JSON_MODIFY(profile ,'$.class_cod_y', null)
假设:每个JSON记录仅包含键class_cod_*
一次。希望只有有限的行可以在其中手动运行更新语句
解决方案:
我认为您不能对path
中的JSON_MODIFY()
参数使用通配符。但是,如果您使用SQL Server 2017+,并且profile
列中的JSON对象只有一个class_cod_*
键,则可以将JSON_MODIFY()
与变量一起用作path
的值和以下语句:
表格:
CREATE TABLE Data (profile nvarchar(max));
INSERT INTO Data (profile) VALUES (N'{"name":"goofy","class_cod_x":"1345"}')
INSERT INTO Data (profile) VALUES (N'{"name":"donald","class_cod_y":"1457"}')
INSERT INTO Data (profile) VALUES (N'{"name":"tom"}')
INSERT INTO Data (profile) VALUES (N'{"name":"goofy","class_cod_x":"1345","age":10}')
声明:
UPDATE Data
SET profile = JSON_MODIFY(profile, CONCAT('$."', j.[key], '"'), NULL)
FROM Data d
CROSS APPLY OPENJSON(d.profile) j
WHERE j.[key] LIKE N'class_cod%'
结果:
profile
{"name":"goofy"}
{"name":"donald"}
{"name":"tom"}
{"name":"goofy","age":10}
附加选项:
如果profile
列中的JSON具有多个class_cod_*
密钥,作为一个附加选项,您可以尝试生成和执行动态语句(SQL Server 2017+需要使用STRING_AGG
进行聚合,用于SQL Server 2016,您应该使用FOR XML PATH('')
)。请注意,您需要使用lax
模式(默认设置)来指定path
引用的属性不必存在:
DECLARE @stm nvarchar(max)
SELECT @stm = STRING_AGG(
CONCAT('UPDATE Data SET profile = JSON_MODIFY(profile, ''lax $."', t.[key], '"'', NULL)'),
'; '
)
FROM (
SELECT DISTINCT j.[key]
FROM Data d
CROSS APPLY OPENJSON(d.profile) j
WHERE j.[key] LIKE N'class_cod%'
) t
PRINT @stm
EXEC sp_executesql @stm