OPENJSON 要求兼容性级别 130,即SQLSERVER2016以上版本

SQLServer中OPENJSON函数的用法_json

1、默认输出的 OPENJSON

在不提供结果的显式架构的情况下使用 OPENJSON 函数时(在 OPENJSON 之后不使用 WITH 子句),该函数将返回包含以下三列的表:

  1. 输入对象中属性的名称(或输入数组中元素的索引)。
  2. 属性或数组元素的值。
  3. 类型(例如,字符串、数字、布尔值、数组或对象)。

OPENJSON 以单独的行返回 JSON 对象的每个属性或数组的每个元素。

示例1:JSON 对象的每个属性返回一行

DECLARE @json NVARCHAR(MAX)
 
SET @json='{
    "姓名": "张三", 
    "年龄": 25, 
    "地址": {
        "省": "浙江", 
        "市": "杭州"
    }, 
    "特长": [
        "删库", 
        "甩锅", 
        "跑路"
    ]
}';
 
SELECT * FROM OPENJSON(@json);

SQLServer中OPENJSON函数的用法_数组_02

示例2:数组的每个元素返回一行

DECLARE @json NVARCHAR(MAX)
 
SET @json='[
    "跑路", 
    24, 
    {
        "姓名": "张三"
    }, 
    [
        1, 
        2
    ]
]';
 
SELECT * FROM OPENJSON(@json)

SQLServer中OPENJSON函数的用法_JSON_03

2、显式结构的 OPENJSON

在 OPENJSON 函数的 WITH 子句指定结果的架构,该函数返回的表只包含 WITH 子句中定义的列。

在可选的 WITH 子句中,指定输出列、列类型和每个输出值的 JSON 源属性的路径。 

OPENJSON 循环访问 JSON 对象的数组,读取每一列指定路径上的值,并将值转换为指定类型。

示例1:从json中解析数据为二维表

DECLARE @json NVARCHAR(MAX)
SET @json='{
	"name":"张三",
	"age":25,
    "skills": [
        "删库", 
        "甩锅", 
        "跑路"
    ]
}';

-- 其中 $ 表示根路径
SELECT 
    JSON_VALUE(@json, '$.name') as name,
	JSON_VALUE(@json, '$.age') as age,
	skills
FROM 
    OPENJSON(@json, '$.skills') 
    WITH(skills varchar(20) '$')

SQLServer中OPENJSON函数的用法_数组_04

示例2:从数组中解析数据为二维表

DECLARE @json NVARCHAR(MAX) = '[{
    "name":"张三",
    "age":25,
    "skills": [
        "删库", 
        "甩锅", 
        "干饭"
    ]
},
{
    "name":"李四",
    "age":27,
    "skills": [
        "画饼", 
        "跑路"
    ]
}]';

SELECT 
    JSON_VALUE(value, '$.name') AS 姓名,
    JSON_VALUE(value, '$.age') AS 年龄,
    skill.特长
FROM 
    OPENJSON(@json) AS items -- 遍历JSON数组的每一项
    CROSS APPLY OPENJSON(items.value, '$.skills') -- 针对每个项中的skills数组
    WITH(
        特长 varchar(20) '$'
    ) AS skill;
    
 --在OPENJSON的外部调用中使用了value关键字来引用每个JSON对象(即人员信息),
 --而在内部调用中继续使用items.value来针对特定对象的skills属性进行遍历。
 --这样就可以正确地获取每个人员的姓名、年龄以及他们的技能特长,避免了列名无效的错误。

SQLServer中OPENJSON函数的用法_数组_05

示例3:从数组中解析数据为二维表(带嵌套json对象)

DECLARE @json NVARCHAR(MAX) = '[
    {
        "name": "张三", 
        "age": 25, 
        "address": {
            "province": "四川", 
            "city": "成都"
        }, 
        "skills": [
            "删库", 
            "甩锅", 
            "干饭"
        ]
    }, 
    {
        "name": "李四", 
        "age": 27, 
        "address": {
            "province": "浙江", 
            "city": "杭州"
        }, 
        "skills": [
            "画饼", 
            "跑路"
        ]
    }
]';

SELECT 
    JSON_VALUE(items.value, '$.name') AS name,
    JSON_VALUE(items.value, '$.age') AS age,
    addr.province AS province,
    addr.city AS city,
    skill.skills
FROM 
    OPENJSON(@json) AS items
    CROSS APPLY OPENJSON(items.value, '$.address') WITH(
        province varchar(20) '$.province',
        city varchar(20) '$.city'
    ) AS addr
    CROSS APPLY OPENJSON(items.value, '$.skills') WITH(
        skills varchar(20) '$'
    ) AS skill;
    
 --在本示例中,添加了一个CROSS APPLY子句来处理address字段中的嵌套JSON对象。
 --通过WITH子句定义province和city两个列来分别提取这些值。

SQLServer中OPENJSON函数的用法_JSON_06

解析钉钉OA表单

SELECT  
  t.表单名,
	t.processCode, 
	t.processInstanceId, 
	dateadd(hour,-8,t.createTime) as createTime,   --对齐时区
	dateadd(hour,-8,t.finishTime) as finishTime,   --对齐时区
	t.result,  
    result.businessId AS businessId,  
    result.title AS title,  
    formComponentValues.name AS name,  
    formComponentValues.value AS value
FROM  
    OA表单数据 t  
CROSS APPLY OPENJSON(t.data, '$.result') WITH (  
    businessId VARCHAR(8000) '$.businessId',  
    title VARCHAR(8000) '$.title'
) AS result
CROSS APPLY OPENJSON(t.data, '$.result.formComponentValues') WITH (  
    name VARCHAR(8000) '$.name',  
    value VARCHAR(8000) '$.value'
) AS formComponentValues 
where formComponentValues.name is not null

示例

--创建表并定义一个nvarchar(max)类型字段的表
CREATE TABLE Products (
    ProductId int PRIMARY KEY,
    Name nvarchar(50),
    Attributes nvarchar(max)
);

--插入两行数据
INSERT INTO Products (ProductId, Name, Attributes) VALUES (1, 'Widget', N'{"Color": "Blue", "Size": "Medium" ,"userid":[{"id":"001","name":"张三"},{"id":"002","name":"李四"},{"id":"003","name":"王五"}]}');
INSERT INTO Products (ProductId, Name, Attributes) VALUES (2, 'Gadget', N'{"Color": "Red", "Size": "Max" ,"userid":[{"id":"101","name":"张三101"},{"id":"102","name":"李四102"},{"id":"103","name":"王五103"}]}');

SQLServer中OPENJSON函数的用法_JSON_07

原始数据表

SQLServer中OPENJSON函数的用法_JSON_08

字段 Attributes 的 json 结构

-- 解析 JSON 字符串并展开为行
SELECT 
t.ProductId
,t.name
,t1.Color
,t1.Size
,t2.id
,t2.name
FROM Products t
CROSS APPLY OPENJSON(Attributes)
WITH (Color nvarchar(50) '$.Color',
      Size nvarchar(50) '$.Size') as t1
CROSS APPLY OPENJSON(Attributes, '$.userid') 
WITH (id VARCHAR(8000) '$.id',  
    name VARCHAR(8000) '$.name') as t2

SQLServer中OPENJSON函数的用法_数组_09

解析为标准二维表