【问题标题】:Consume JSON via OPENJSON and save in table - SQL Server 2016通过 OPENJSON 使用 JSON 并保存在表中 - SQL Server 2016
【发布时间】:2018-03-21 18:33:53
【问题描述】:

我们最近将后端数据库从 SQL Server 2012 升级到了 SQL Server 2016,我意识到它支持 JSON 对象。我们的网络服务之一以以下格式返回数据,我正在尝试使用 OPENJSON 函数直接使用它。

{
"RESULT_1": {
    "columns": ["col1", "col2", "col3", "col4"],
    "data": [
        ["0", null, "12345", "other"],
        ["1", "a", "54321", "MA"],
        ["0", null, "76543", "RI"]
    ]
   }
}

我想确保从“列部分”读取列名,并确保在 SQL Server 2016 中读取和推送正确的数据。

DECLARE @Json_Array2 nvarchar(max) = '{
"RESULT_1": {
    "columns": ["col1", "col2", "col3", "col4"],
    "data": [
        ["0", null, "12345", "other"],
        ["1", "a", "54321", "MA"],
        ["0", null, "76543", "RI"]
    ]
} }';

SELECT [key], value
FROM OPENJSON(@Json_Array2,'$.RESULT_1.columns')

SELECT [key], value
FROM OPENJSON(@Json_Array2,'$.RESULT_1.data')

通过上述语句,我能够提取列和数据数组。是否可以将这些数据转储到具有相同列名的平面表(已经存在)中?

我可以通过以下方式查看某一特定行的所有值:

SELECT [key], value
FROM OPENJSON(@Json_Array2,'$.RESULT_1.data[0]')


key value
0   0
1   NULL
2   12345
3   other

感谢任何指针。

谢谢

【问题讨论】:

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


    【解决方案1】:

    如果我理解正确,您正在尝试从“数据”数组中提取所有元素

    Col1    Col2    Col3    Col4
    0      NULL    12345    other
    1      a       54321    MA
    0      NULL    76543    RI
    

    假设您的 Json 结构不会改变,您可以使用以下查询来实现:

    SET NOCOUNT ON 
    IF OBJECT_ID ('tempdb..##ToPvt') IS NOT NULL DROP TABLE ##ToPvt
    DECLARE @Cmd NVARCHAR(MAX)=''
    DECLARE @Table TABLE (Col1 nvarchar(100), Col2 nvarchar(100), Col3 nvarchar(100) , Col4 nvarchar(100))
    DECLARE @Json_Array2 nvarchar(max) = '{
    "RESULT_1": {
        "columns": ["col1", "col2", "col3", "col4"],
        "data": [
            ["0", null, "12345", "other"],
            ["1", "a", "54321", "MA"],
            ["0", null, "76543", "RI"]
        ]
    } }';
    
    ;WITH Cols ([Key], [Value]) as
    (
    SELECT [key], value
    FROM OPENJSON(@Json_Array2,'$.RESULT_1.columns')
    )
    
    , [Rows] as
    (
    SELECT ROW_NUMBER () OVER (ORDER BY [Key]) Seq, [key], value
    FROM OPENJSON(@Json_Array2,'$.RESULT_1.data')
    ) 
    ,ToPvt as 
    (
    SELECT c.[Key]+1 Cols, x.Value , 'col'+CONVERT(VARCHAR(10),ROW_NUMBER () OVER (PARTITION BY c.Value ORDER BY t.[Key])) Seq
     FROM [Rows] t
     INNER JOIN Cols C
     ON t.[key] = c.[key]
     CROSS APPLY OPENJSON(t.value) X
     )
    
     SELECT * 
     INTO ##ToPvt
     FROM ToPvt 
    
     ;WITH Final (Cmd) as
     (
     SELECT DISTINCT 'SELECT [col1], [col2], [col3],[col4] FROM ##ToPvt 
                PIVOT
                    (
                    MAX([Value]) FOR Seq IN ([col1], [col2], [col3],[col4])
                    ) T
                 WHERE Cols = '+CONVERT(VARCHAR(10),Cols)+'
                    ;'
     FROM ##ToPvt
     )
    
     SELECT @Cmd += Cmd
     FROM Final 
    
     INSERT INTO @Table 
     EXEC sp_executesql @Cmd
    
     SELECT * 
     FROM @Table
    

    【讨论】:

    • 谢谢@hkravitz。太棒了。是否可以分享一些关于 ToPvt 和 Final (Cmd) 正在做什么的细节?另外,如果我真的不需要使用列名而只插入“数据”,那么最好的方法是什么?
    • @DataRiver,ToPvt 部分正在为动态透视准备结果集,注意 OPENJSON 返回一个键值结果集,您需要对其进行透视才能将数据插入到表中n 列。如果您将使用简单的枢轴,您将获得 col1 到 col4 的每个组合的 1 行。这里的技巧是为 JSON 中的每个数据数组创建一个数据透视语句。如果您想提取“数据”元素的所有值,只需使用 select * from [rows] T cross apply OPENJSON(T.[value]) x,您将获得列为键值输出的所有值。如果您需要更多帮助,请告诉我
    • 非常感谢@hkravitz 的解释。我将对此进行调整,看看它是否适合我的应用程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多