【问题标题】:SQL Server 2016 JSON: Select array of strings instead of array of objectsSQL Server 2016 JSON:选择字符串数组而不是对象数组
【发布时间】:2016-09-12 14:50:32
【问题描述】:

我是 SQL Server 中 JSON 的新手,不知道如何返回一个简单的字符串数组:

DECLARE @T TABLE ([value] NVARCHAR(MAX))

INSERT INTO @T ([value]) VALUES ('foo')
INSERT INTO @T ([value]) VALUES ('bar')
INSERT INTO @T ([value]) VALUES ('test')
INSERT INTO @T ([value]) VALUES ('ok')

SELECT [value]
FROM @T
FOR JSON PATH

这会返回一个对象数组:

[{"value":"foo"},{"value":"bar"},{"value":"test"},{"value":"ok"}]

我希望它返回:

["foo","bar","test","ok"]

这还能做到吗?

【问题讨论】:

  • 我从这个 Q&A 中学到的东西 = SQL Server 2016 宣传 JSON 支持,但没有提供一种直接的方式来查询表并返回 JSON 格式的数组。为什么我们必须手动构建数组字符串?呃。

标签: arrays sql-server json sql-server-2016


【解决方案1】:

在 SQL2017 中,使用 STRING_AGG 代替 json。此函数最适合生成以逗号分隔的值列表。

https://docs.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql

SELECT town, STRING_AGG (email, ';') AS emails 
FROM dbo.Employee 
GROUP BY town;

【讨论】:

  • 如果我执行insert into @t ([value]) values ('test " , '' ') 则会中断,因为for json path 处理字符转义string_agg 会破坏输出。如果您确定源不包含任何需要转义的字符,这只会更快。
  • STRING_ESCAPE 来帮助解决这个问题。 docs.microsoft.com/en-us/sql/t-sql/functions/…
【解决方案2】:

基于 Loui Bao 和 Roman 的回答:

declare @t table ([value] nvarchar(max))

insert into @t ([value]) values ('foo')
insert into @t ([value]) values ('bar')
insert into @t ([value]) values ('test')
insert into @t ([value]) values ('ok')

SELECT
    JSON_QUERY((SELECT CONCAT('["',STRING_AGG([value], '","'),'"]') FROM @t)) As MuhArray
    OtherValue,
    AnotherValue
FROM MyTableOValues
FOR JSON PATH

这是创建一个简单值的 JSON 有效数组并将其分配给属性 MuhArray。来自此的 JSON 输出将是:

[{
  MuhArray: ["foo", "bar", "test", "ok"],
  OtherValue: "Value",
  AnotherValue: "AnotherValue"
}]

OtherValueAnotherValue 接收表中对应的任何值。通过一些摆弄,您也可以选择不将其构建为选择列表中的子查询,而是作为主查询主体中的简单连接。在我看来,在选择列表中使用子查询可以消除对distinct 关键字的需求。

【讨论】:

    【解决方案3】:

    在 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 dbo.ufnToRawJsonArray( (SELECT value FROM mytable for json path), 'value')
    

    【讨论】:

      【解决方案4】:

      基于 Roman 的回答:

      declare @t table ([value] nvarchar(max))
      
      insert into @t ([value]) values ('foo')
      insert into @t ([value]) values ('bar')
      insert into @t ([value]) values ('test')
      insert into @t ([value]) values ('ok')
      
      select concat('[', string_agg(concat('"', [value], '"'), ','), ']')
      from @t
      

      输出:

      ["foo","bar","test","ok"]

      【讨论】:

        【解决方案5】:

        这应该可以帮助您入门。 2016 有几种使用 JSON 的方法。此方法定义 JSON 字符串,从中提取值,然后使用 XML 技巧将多行合并为一行。

        DECLARE @T TABLE ([value] NVARCHAR(MAX))
        
        INSERT INTO @T ([value])
        VALUES ('foo')
        
        INSERT INTO @T ([value])
        VALUES ('bar')
        
        INSERT INTO @T ([value])
        VALUES ('test')
        
        INSERT INTO @T ([value])
        VALUES ('ok')
        
        DECLARE @JSON NVARCHAR(MAX) = (
                SELECT *
                FROM @T
                FOR JSON PATH
                );
        
        WITH cte
        AS (
            SELECT *
            FROM OPENJSON(@json) WITH (NAME VARCHAR(10) '$.value')
            )
        SELECT QUOTENAME(left(names, LEN(names) - 1) )AS names
        FROM (
            SELECT DISTINCT (
                    SELECT QUOTENAME(NAME,'"') + ',' AS [text()]
                    FROM cte
                    FOR XML PATH('')
                    ) names
            FROM cte
            ) x
        

        【讨论】:

          【解决方案6】:

          将以下代码用于 Sql Server 2016 的任何版本

          declare @t table ([value] nvarchar(max))
          
          insert into @t ([value]) values ('foo')
          insert into @t ([value]) values ('bar')
          insert into @t ([value]) values ('test')
          insert into @t ([value]) values ('ok')
          
          DECLARE @values nvarchar(max) = N'[]'; 
          SELECT @values = JSON_MODIFY(@values,'append $',[value]) 
          FROM @t SELECT @values
          

          【讨论】:

          • 你可以做 ` DECLARE @values nvarchar(max) = N'[]'; SELECT @values = JSON_MODIFY(@values,'append $',[value]) FROM @t SELECT @values` 实际上
          【解决方案7】:

          另一种解决方案

          DECLARE @T TABLE ([value] NVARCHAR(MAX))
          
          INSERT INTO @T ([value]) VALUES ('foo')
          INSERT INTO @T ([value]) VALUES ('bar')
          INSERT INTO @T ([value]) VALUES ('test')
          INSERT INTO @T ([value]) VALUES ('ok')
          
          SELECT JSON_QUERY('[' + STUFF((SELECT ',"' +  [value] + '"' from  @T FOR XML PATH('')), 1, 1, '')+']')
          

          返回:

          ["foo","bar","test","ok"]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-12-02
            • 1970-01-01
            • 1970-01-01
            • 2016-12-18
            • 2017-07-13
            • 1970-01-01
            • 1970-01-01
            • 2014-04-15
            相关资源
            最近更新 更多