在SQL Server中解析JSON

在SQL Server中解析JSON,sql,sql-server,json,sql-server-2016,Sql,Sql Server,Json,Sql Server 2016,参考Microsoft提供的示例: DECLARE @json NVARCHAR(MAX) SET @json = N'[ { "id" : 2,"info": { "name": "John", "surname": "Smith" }, "age": 25 }, { "id" : 5,"info": { "name": "Jane", "surname": "Smith" }, "dob": "2005-11-04T12:00:00" } ]'

参考Microsoft提供的示例:

DECLARE @json NVARCHAR(MAX)
SET @json =  
N'[  
       { "id" : 2,"info": { "name": "John", "surname": "Smith" }, "age": 25 },  
       { "id" : 5,"info": { "name": "Jane", "surname": "Smith" }, "dob": "2005-11-04T12:00:00" }  
 ]'  

SELECT *  
FROM OPENJSON(@json)  
  WITH (id int 'strict $.id',  
        firstName nvarchar(50) '$.info.name', lastName nvarchar(50) '$.info.surname',  
        age int, dateOfBirth datetime2 '$.dob') 
当JSON数据中包含数组时,例如:

DECLARE @json NVARCHAR(MAX)
SET @json =  
N'[  
       { "id" : 2,"info": { "name": "John", "surname": "Smith" }, 
         "Phones": ["123","345","678"] // like here
        }   
]' 
是否有任何方法可以连接解析数据上的数组以获得如下内容:

 Id     First Name      Last Name    Phone
 2      John            Smith        123
 2      John            Smith        345
 2      John            Smith        678
DECLARE @json NVARCHAR(MAX)
SET @json =  
N'[  
    { "id" : 2,"info": { "name": "John", "surname": "Smith" }, "Phones": ["123","345","678"] },
    { "id" : 3,"info": { "name": "Jane", "surname": "Smith" }, "Phones": ["321","543"] }
]';

WITH CTE AS (
    SELECT id, firstName, lastName, phones
    FROM OPENJSON(@json)
    WITH (
        id INT 'strict $.id',  
        firstName NVARCHAR(50) '$.info.name', 
        lastName NVARCHAR(50) '$.info.surname',
        phones NVARCHAR(MAX) '$.Phones' AS JSON
    )
)
SELECT c.id, c.firstName, c.lastName, p.value as phone
FROM CTE c
    CROSS APPLY OPENJSON(c.phones) p
SELECT ID,  FirstName, LastName, value 
FROM OPENJSON(@json)
WITH(ID int '$.id', 
     FirstName nvarchar(50) '$.info.name',
     LastName nvarchar(50) '$.info.surname',
     Phones nvarchar(max) '$.Phones' AS Json)
CROSS APPLY OPENJSON(Phones)

OUTER APPLY
是您的朋友。让我们把这两种行混在一起,以便更好地衡量

DECLARE @json NVARCHAR(MAX)
SET @json = N'
[
  {
    "id": 2,
    "info": {
      "name": "John",
      "surname": "Smith"
    },
    "age": 25,
    "Phones": [
      "123",
      "345",
      "678"
    ]
  },
  {
    "id": 5,
    "info": {
      "name": "Jane",
      "surname": "Smith"
    },
    "dob": "2005-11-04T12:00:00"
  }
]'  

SELECT id, [name], [surname], age, dateOfBirth, number
FROM (
    SELECT * 
    FROM OPENJSON(@json)
    WITH (
        id          INT             'strict $.id',
        [name]      NVARCHAR(50)    '$.info.name',
        [surname]   NVARCHAR(50)    '$.info.surname',
        age         INT,
        dateOfBirth DATETIME2       '$.dob',
        Phones      NVARCHAR(MAX)   AS JSON
    )
) AS people
OUTER APPLY OPENJSON(Phones)
WITH (
    number NVARCHAR(50) '$'
)
结果:

+----+------+---------+------+-----------------------------+--------+
| id | name | surname | age  |         dateOfBirth         | number |
+----+------+---------+------+-----------------------------+--------+
|  2 | John | Smith   | 25   | NULL                        | 123    |
|  2 | John | Smith   | 25   | NULL                        | 345    |
|  2 | John | Smith   | 25   | NULL                        | 678    |
|  5 | Jane | Smith   | NULL | 2005-11-04 12:00:00.0000000 | NULL   |
+----+------+---------+------+-----------------------------+--------+

您必须分两次完成:

  • 提取每个人的数据并将电话号码数组保留为JSON
  • 使用CROSS/OUTER APPLY解析每个人的电话号码数组,并将结果连接在一起
  • 大概是这样的:

     Id     First Name      Last Name    Phone
     2      John            Smith        123
     2      John            Smith        345
     2      John            Smith        678
    
    DECLARE @json NVARCHAR(MAX)
    SET @json =  
    N'[  
        { "id" : 2,"info": { "name": "John", "surname": "Smith" }, "Phones": ["123","345","678"] },
        { "id" : 3,"info": { "name": "Jane", "surname": "Smith" }, "Phones": ["321","543"] }
    ]';
    
    WITH CTE AS (
        SELECT id, firstName, lastName, phones
        FROM OPENJSON(@json)
        WITH (
            id INT 'strict $.id',  
            firstName NVARCHAR(50) '$.info.name', 
            lastName NVARCHAR(50) '$.info.surname',
            phones NVARCHAR(MAX) '$.Phones' AS JSON
        )
    )
    SELECT c.id, c.firstName, c.lastName, p.value as phone
    FROM CTE c
        CROSS APPLY OPENJSON(c.phones) p
    
    SELECT ID,  FirstName, LastName, value 
    FROM OPENJSON(@json)
    WITH(ID int '$.id', 
         FirstName nvarchar(50) '$.info.name',
         LastName nvarchar(50) '$.info.surname',
         Phones nvarchar(max) '$.Phones' AS Json)
    CROSS APPLY OPENJSON(Phones)
    

    嗯,你总是可以这样做:

     Id     First Name      Last Name    Phone
     2      John            Smith        123
     2      John            Smith        345
     2      John            Smith        678
    
    DECLARE @json NVARCHAR(MAX)
    SET @json =  
    N'[  
        { "id" : 2,"info": { "name": "John", "surname": "Smith" }, "Phones": ["123","345","678"] },
        { "id" : 3,"info": { "name": "Jane", "surname": "Smith" }, "Phones": ["321","543"] }
    ]';
    
    WITH CTE AS (
        SELECT id, firstName, lastName, phones
        FROM OPENJSON(@json)
        WITH (
            id INT 'strict $.id',  
            firstName NVARCHAR(50) '$.info.name', 
            lastName NVARCHAR(50) '$.info.surname',
            phones NVARCHAR(MAX) '$.Phones' AS JSON
        )
    )
    SELECT c.id, c.firstName, c.lastName, p.value as phone
    FROM CTE c
        CROSS APPLY OPENJSON(c.phones) p
    
    SELECT ID,  FirstName, LastName, value 
    FROM OPENJSON(@json)
    WITH(ID int '$.id', 
         FirstName nvarchar(50) '$.info.name',
         LastName nvarchar(50) '$.info.surname',
         Phones nvarchar(max) '$.Phones' AS Json)
    CROSS APPLY OPENJSON(Phones)
    
    希望这有帮助。

    您可以使用C#library


    它是一个功能强大的工具,如果Json具有嵌套级别,它可以维护Json中的sql关系

    伟大的解决方案,我被困在这个
    电话NVARCHAR(MAX)作为JSON的问题上,所以实现了它像值一样clause@TheGameiswar:如果严格限制(和/或已知)值的数量,则从数组中显式提取它们可能比第二次
    OPENJSON
    要快。但是我没有任何计时JSON解析的经验,所以现在还不需要优化。:-)是的,你是对的,刚刚看到了执行计划,原始Json的成本为0,外部应用下面的Json的成本为20