使用JSON_MODIFY向数组添加范围

时间:2019-11-18 10:29:05

标签: sql json sql-server tsql

我正在尝试使用uniform_data = np.random.rand(10, 12)将一个数组添加到另一个数组。
情况是,我在数据库中存储了数组类型的json数据。看起来像这样:

data.dat

然后我得到了另一组也是数组形式的数据:

JSON_MODIFY

我正在尝试使用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"}]]

我在这个过程中迷失了方向,不知道在哪里可以找到这种功能。
我将在C#服务中使用它来直接通过代码进行修改。这就是为什么我不能同时使用Store过程和函数的原因。

  

编辑#1:

关于@Salman A的回复,我感谢您的回答,但正如我之前所说,事情是很难在通过代码运行的查询中使用。就是

Add-Range

我已经尝试过适应我喜欢的答案:

[{"name":"base"},{"name":"test1"},{"name":"example1"}]

实际上,如果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' 仅包含1个项目,则可以使用,但是如果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' 中包含1个以上的项目,则会出现错误:

  

子查询返回了多个值。当子查询遵循= .....

时,不允许这样做

@test1中使用逻辑的方式是什么

1 个答案:

答案 0 :(得分:5)

您可以使用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
);

Demo on db<>fiddle