我正在尝试使用将数组添加到另一个数组JSON_MODIFY
。
情况是,我在数据库中存储了数组类型的json数据。看起来像这样:
declare @base nvarchar(max) = '[{"name":"base"}]';
我得到的另一组数据也是数组形式的:
declare @test1 nvarchar(max) = '[{"name":"test1"},{"name":"example1"}]';
我正在尝试使用JSON_MODIFY
和JSON_QUERY
魔术将它们附加在一起,但这给了我意外的结果。
declare @base nvarchar(max) = '[{"name":"base"}]';
declare @test1 nvarchar(max) = '[{"name":"test1"},{"name":"example1"}]';
set @base = JSON_MODIFY(@base,'append $',JSON_QUERY(@test1));
select @base;
输出:
[{"name":"base"}, [{"name":"test1"},{"name":"example1"}]]
但是我想要的是使用这些方法使其像以下那样工作Add-Range
:
[{"name":"base"},{"name":"test1"},{"name":"example1"}]
我对这个过程有些迷惑,我不知道在哪里可以找到这种功能。
我将在C#服务中使用它来直接通过代码进行修改。这就是为什么我不能同时使用Store过程和函数的原因。
编辑#1:
关于@Salman A的答复,我非常感谢您的回答,但正如我之前所说,事情很难在通过代码运行的查询中使用。这是:
declare @test1 nvarchar(max) = '[{"name":"test1"},{"name":"example1"}]'; UPDATE dbo.ExampleTable SET [Data] = JSON_MODIFY([Data], 'append $', JSON_QUERY(@test1)) WHERE [UniqueId] = 'some_guid_here'
我已经尝试过适应我喜欢的答案:
declare @test1 nvarchar(max) = '[{"name":"test1"},{"name":"example1"}]'; UPDATE dbo.ExampleTable SET [Data] = ( select [Data] = JSON_MODIFY([Data],'append $',item) from OPENJSON(@test1) with ([item] nvarchar(max) '$' as JSON) ) WHERE [UniqueId] = 'some_id'
实际上,如果@test1
只有1个项目,则可以使用,但如果中有1个以上@test1
,则会出现错误:
子查询返回的值超过1。当子查询遵循= ....时,不允许这样做。
在 update set subquery
您可以OPENJSON
用来将数组转换为行,并一一追加项目:
declare @base nvarchar(max) = '[{"name":"base"}]';
declare @test1 nvarchar(max) = '[{"name":"test1"},{"name":"example1"}]';
select @base = json_modify(@base, 'append $', item)
from openjson(@test1)
with ([item] nvarchar(max) '$' as json);
select @base;
返回值:
[{"name":"base"},{"name":"test1"},{"name":"example1"}]
修改后的更新查询答案
如果您使用的是SQL Server 2017+,那么一个比较安全的解决方案是使用串联数组,STRING_AGG
但使用JSON函数构建单个行。在更新查询中使用此想法相对容易:
DECLARE @base NVARCHAR(MAX) = '[{"name":"base"}]'; DECLARE @test NVARCHAR(MAX) = '[{"foo":"bar"},{"baz":"meh"}]'; SELECT '[' + STRING_AGG(jsonstr, ',') WITHIN GROUP (ORDER BY pos) + ']' FROM ( SELECT value, 1000 + [key] FROM OPENJSON(@base) UNION ALL SELECT value, 2000 + [key] FROM OPENJSON(@test) ) AS x(jsonstr, pos);
或者,您可以使用JSON_MODIFY
多次调用的递归CTE 来构建JSON。您可以在更新查询中使用结果:
CREATE TABLE t( id INT NOT NULL PRIMARY KEY IDENTITY, data NVARCHAR(MAX) ); INSERT INTO t(data) VALUES ('[{"name":"1.1"}]'), ('[{"name":"2.1"},{"name":"2.2"}]'); WITH rows(data, pos) AS ( SELECT value, [key] FROM OPENJSON('[{"foo":"bar"},{"baz":"meh"}]') ), rcte(id, data, pos) AS ( SELECT id, data, -1 FROM t UNION ALL SELECT prev.id, JSON_MODIFY(prev.data, 'append $', JSON_QUERY(curr.data)), prev.pos + 1 FROM rcte AS prev JOIN rows AS curr ON curr.pos = prev.pos + 1 ) UPDATE t SET data = ( SELECT TOP 1 data FROM rcte WHERE id = t.id ORDER BY pos DESC );
db <> fiddle上的演示