用于 JSON 输出整数数组的 SQL Server 2016

Posted

技术标签:

【中文标题】用于 JSON 输出整数数组的 SQL Server 2016【英文标题】:SQL Server 2016 for JSON output integer array 【发布时间】:2016-09-26 10:14:44 【问题描述】:

我想使用 SQL Server 2016 的 For JSON 功能获取带有整数数组的 JSON。我被整数数组难住了。

数据库表结构:

declare @Employees table (ID int, Name nvarchar(50))
insert into @Employees values
(1, 'Bob'),
(2, 'Randy')

declare @Permissions table (ID int, PermissionName nvarchar(50))
insert into @Permissions values
(1, 'Post'),
(2, 'Comment'),
(3, 'Edit'),
(4, 'Delete')

declare @EmployeePermissions table (EmployeeID int, PermissionID int)
insert into @EmployeePermissions values
(1, 1),
(1, 2),
(2, 1),
(2, 2),
(2, 3)

期望的结果:

"EmployeePermissions": [
  "Employee":"Bob", "Permissions":[1,2],
  "Employee":"Randy", "Permissions":[1,2,3]
]

这是我得到的最接近的,但不是我想要的。

select
    e.Name as Employee,
    (select 
         convert(nvarchar(10),ep.PermissionID) as PermID 
     from @EmployeePermissions ep 
     where ep.EmployeeID=e.ID 
     for json path) as 'Permissions'
from
    @Employees e
for json path, root('EmployeePermissions')

返回:

"EmployeePermissions": [
  "Employee":"Bob", "Permissions":["permID":1,"permID":2],
  "Employee":"Randy", "Permissions":["permID":1,"permID":2,"permID":3]
]

【问题讨论】:

能否分享下工作代码,有助于给出更多答案 使用 for permID 创建一个视图 /resultset 然后完成结果***.com/questions/10461874/… @Arulkumar - 添加了我最接近的代码。 如果你能忍受来自SQL Server 的有问题的输出,我建议你让消费者知道这些别名。如果您使用的是Json.NET,请查看这个出色的答案:***.com/a/48245381/419761 【参考方案1】:

您可以使用FOR XML PATHSTUFF 使PermissionID 为每个Employee 分隔一个字符串逗号,在其上使用QUOTENANE,然后将所有变量放入变量中并将"[ 替换为[]"]

DECLARE @json NVARCHAR(max)

SELECT @json = REPLACE(REPLACE((
    SELECT  e.Name as [Employee],
            QUOTENAME(STUFF((SELECT ','+CAST(ep.PermissionID as nvarchar(10))
            FROM EmployeePermissions ep
            WHERE e.ID = ep.EmployeeID
            FOR XML PATH('')),1,1,''))
            as [Permissions]
    FROM Employees e 
    FOR JSON AUTO, ROOT('EmployeePermissions')
),'"[','['),']"',']')

SELECT @json

输出:

"EmployeePermissions":[
    "Employee":"Bob","Permissions":[1,2],
    "Employee":"Randy","Permissions":[1,2,3]
]

编辑:

另一种方式:

SELECT '"EmployeePermissions":[' + STUFF((
SELECT  ',"Employee":"' + e.Name + '","Permissions":[' +
        STUFF((SELECT ',' + CAST(PermissionID as nvarchar(10))
        FROM EmployeePermissions ep
        WHERE ep.EmployeeID = e.ID
        FOR XML PATH('')),1,1,'') +']'
FROM Employees e
FOR XML PATH('')),1,1,'') + ']'

输出:

"EmployeePermissions":[
    "Employee":"Bob","Permissions":[1,2],
    "Employee":"Randy","Permissions":[1,2,3]
]

【讨论】:

关闭,虽然我想要一个数字数组,像这样:"Permissions":[1,2,3] 好吧,也许在 SQL Server 的下一个版本中,他们添加的功能是您可以在不命名列的情况下调用 FOR JSON PATH 或以其他方式创建值数组(如 JSON_MODIFY 附加)。但现在它照原样出现。希望你找到你的问题的答案。 :) 感谢 gofr1。在等待 Microsoft 支持 JSON 这么久之后,我发现我已经达到了限制,这让我很难接受。 @JensFrandsen 是的,我很失望,我似乎无法弄清楚如何用我的数据创建一个简单的数组数组。我不想要任何钥匙。 有这方面的消息吗?目前我只是在解析应用程序中的 JSON 输出后立即删除键【参考方案2】:

在 AdventureWorks 2016 CTP3 JSON 示例中,您可以找到一个可以清理键:值对数组并创建数组 od 值的函数:

DROP FUNCTION IF EXISTS dbo.ufnToRawJsonArray
GO
CREATE FUNCTION
[dbo].[ufnToRawJsonArray](@json nvarchar(max), @key nvarchar(400)) returns nvarchar(max)
AS BEGIN
       declare @new nvarchar(max) = replace(@json, CONCAT(',"', @key,'":'),',')
       return '[' + substring(@new, 1 + (LEN(@key)+5), LEN(@new) -2 - (LEN(@key)+5)) + ']'
END

只需提供您的 SELECT FOR JSON 表达式的结果作为 @json 参数和要删除的键的名称作为第二个参数。大概是这样的:

select
e.Name as Employee,
JSON_QUERY(dbo.ufnToRawJsonArray(
    (select 
     convert(nvarchar(10),ep.PermissionID) as PermID 
     from @EmployeePermissions ep 
     where ep.EmployeeID=e.ID 
     for json path)
  , 'PermID'))
   as 'Permissions'
from
@Employees e
for json path, root('EmployeePermissions')

【讨论】:

以上是关于用于 JSON 输出整数数组的 SQL Server 2016的主要内容,如果未能解决你的问题,请参考以下文章

将 java.sql.Array 创建为整数数组以用于准备好的语句 [重复]

根据 SQL 中的 id 将 JSON 格式化为嵌套数组

使用 JSON 数据输出数组数组而不是一个数组来反应 useState Hooks

plpgsql jsonb_set 用于带有嵌套数组的 JSON 对象数组

C6-1 最大子数组和

json serve的使用