在SQL中解析JSON结构

时间:2019-06-26 16:44:07

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

我编写了一个代码,用于从JSON行读取信息到SQL中的表:

declare @pJSON varchar(max) = '
{
    "School": "MiddleSchool",
    "Password": "SchoolPassword",
    "Attributes": [
        {
            "Type": "Exam",
            "Value": "1"
        },
        {
            "Type": "Class",
            "Value": "11b"
        },
        {
            "Type": "Math",
            "Value": [
               {
                    "ExamDate": "2019-01-01",
                    "Points": 100,
                    "Grade": 10,
                    "Notes": "Good"
                }
            ]
        }   
    ]   
}   '


select ExamDate, Points, Grade, Notes   
from OPENJSON(@pJSON, N'$.Attributes[2].Value')    
cross apply openjson ([Value])   
with    
(    
  ExamDate date,    
  Points int,    
  Grade int,    
  Notes varchar(max)    
) as [value]

代码工作正常,但我真的很讨厌N'$.Attributes[2].Value'部分。考试信息可以排在第一,第二,第三位,因此[2]对我而言并不是很有效。您对我有什么建议,我如何改进此代码?谢谢!

1 个答案:

答案 0 :(得分:1)

您可以使用JSON_QUERY

select ExamDate, Points, Grade, Notes   
from OPENJSON(JSON_QUERY(@pJSON, N'$.Attributes'))
with    
(    
  ExamDate date      N'$.Value[0].ExamDate',  -- here 0 because Value is array too
  Points int         N'$.Value[0].Points',    
  Grade int          N'$.Value[0].Grade',    
  Notes varchar(max) N'$.Value[0].Notes'
) as [value]
WHERE ExamDate IS NOT NULL;

db<>fiddle demo


编辑:

在最初的问题中,只有一门考试。如果数组可能包含的代码不止一个,则应进行调整:

SELECT s2.[key]
      ,ExamValue = JSON_VALUE(s2.value, '$.ExamDate')
      ,Points    = JSON_VALUE(s2.value, '$.Points')
      ,Grade     = JSON_VALUE(s2.value, '$.Grade')
      ,Notes     = JSON_VALUE(s2.value, '$.Notes')
FROM OPENJSON(JSON_QUERY(@pJSON, N'$.Attributes')) s
CROSS APPLY OPENJSON(JSON_QUERY(s.value, N'$.Value')) s2;

-- or
SELECT [value].*
FROM OPENJSON(JSON_QUERY(@pJSON, N'$.Attributes'))
CROSS APPLY OPENJSON(JSON_QUERY(value, N'$.Value'))
with    
(    
  ExamDate date      N'$.ExamDate', 
  Points int         N'$.Points',    
  Grade int          N'$.Grade',    
  Notes varchar(max) N'$.Notes'
) as [value];

db<>fiddle demo