sqlserver存储过程中入参使用JSON

发布于:2025-06-15 ⋅ 阅读:(18) ⋅ 点赞:(0)

本文主要介绍,在sqlserver存储过程中,使用JSON字符串作为入参,并解析使用。

JSON 相关的方法:

  • ISJSON: 作用:判断一段字符串是否是标准的 json
  • FOR JSON PATH:作用:直接查询数据成 json 格式 ,类似于之前的查询一个 xml (FOR XML PATH)
  • JSON_VALUE:作用:获取json中的节点值,获取json中的节点值,包含标量值、嵌套对象属性
  • JSON_QUERY:作用:提取嵌套对象和嵌套数组
  • JSON_MODIFY:作用:更新一段JSON的内容,修改 JSON 对象里的属性值,删除 JSON 对象里的某一个属性,增加属性
  • OPENJSON:解析一段 json 内容

使用示例:

以下json字符串示例中,包含嵌套对象、数组,后面以此json为示例演示。

DECLARE @json NVARCHAR(MAX) = N'{
    "student_id": 10,
    "student_name": "张三",
    "student_age": 18,
    "student_class": {
        "class_id": 2,
        "class_code": "snj2",
        "class_name": "三年级2班"
    },
    "student_subjects": [
        {
            "subject_id": 1,
            "subject_name": "语文"
        },
        {
            "subject_id": 2,
            "subject_name": "数学"
        }
    ]
}';

在JSON中,分为标量值可非标量值:

  • 标量值:
    • 定义:单一的、不可再分解的基础数据类型
    • 例如:上面JSON串,顶层字段student_id、student_name、student_age
  • 非标量值:
    • 定义:可包含多个元素或键值对的复合数据结构
    • 例如:上面JSON串,student_class节点(嵌套对象),student_subjects(嵌套数组)
结构类型 路径表达式 数据类型
标量值 $.student_id 数值
标量值 $.student_name 字符串
标量值 $.student_age 数值
嵌套对象 $.student_class JSON 对象
嵌套数组 $.student_subjects JSON 数组

标量值

解析顶层字段标量值student_id、student_name、student_age

	--方法1,直接JSON_VALUE获取

	--方法1,直接使用JSON_VALUE获取顶层标量字段
	SELECT 
        JSON_VALUE(@json, '$.student_id') AS student_id,
        JSON_VALUE(@json, '$.student_name') AS student_name,
        JSON_VALUE(@json, '$.student_age') AS student_age
	--方法2,使用OPENJSON解析
	 SELECT 
            id as student_id,
            name as student_name,
            age as student_age
        FROM OPENJSON(@json) WITH (
            id INT '$.student_id',
            name NVARCHAR(50) '$.student_name',
            age INT '$.student_age'
        );
    

在这里插入图片描述

嵌套对象

获取非标量值嵌套对象student_class节点中的class_id、class_code、class_name

--方法1,直接使用JSON_VALUE,通过$.student_class.xx获取
 	SELECT 
		JSON_VALUE(@json, '$.student_class.class_id') AS class_id,
		JSON_VALUE(@json, '$.student_class.class_code') AS class_code,
		JSON_VALUE(@json, '$.student_class.class_name') AS class_name
	--方法2,使用OPENJSON解析,用$.student_class.xx获取
	 SELECT 
            class_id,
            class_code,
            class_name
        FROM OPENJSON(@json) WITH (
            class_id NVARCHAR(50) '$.student_class.class_id',
            class_code NVARCHAR(50) '$.student_class.class_code',
            class_name NVARCHAR(50) '$.student_class.class_name'
        ) AS class
	--方法3,先JSON_QUERY获取student_class节点,然后OPENJSON解析
	  SELECT 
			class_id,
            class_code,
            class_name
    FROM OPENJSON(JSON_QUERY(@json, '$.student_class')) 
    WITH (
        class_id NVARCHAR(50) '$.class_id',
        class_code NVARCHAR(50) '$.class_code',
        class_name NVARCHAR(50) '$.class_name'
    ) AS class

在这里插入图片描述

嵌套数组

获取非标量嵌套数组student_subjects中的属性值

	--直接使用JSON_VALUE? 不可以,获取不到
	SELECT 
		JSON_VALUE(@json, '$.student_subjects.subject_id') AS class_id,
		JSON_VALUE(@json, '$.student_subjects.subject_name') AS class_code
	
	--使用OPENJSON解析+$.student_subjects.xx读取? 不可以,获取不到
	 SELECT 
            subject_id,
            subject_name
        FROM OPENJSON(@json) WITH (
            subject_id NVARCHAR(50) '$.student_subjects.subject_id',
            subject_name NVARCHAR(50) '$.student_subjects.subject_name'
        ) AS subject

	--正确方法:先使用JSON_QUERY获取$.student_subjects节点,再OPENJSON解析
	 SELECT 
        subject_id,
        subject_name
    FROM OPENJSON(JSON_QUERY(@json, '$.student_subjects')) 
    WITH (
        subject_id INT '$.subject_id',
        subject_name NVARCHAR(50) '$.subject_name'
    ) AS subject;

在这里插入图片描述

普通数组

--基本类型数组
DECLARE @json NVARCHAR(MAX) = N'[
    10,
    20,
    30
]';
SELECT value AS Number
FROM OPENJSON(@json);

--引用类型数组
DECLARE @json2 NVARCHAR(MAX) = N'[
    {"id":1,"name":"张三"},
    {"id":2,"name":"李四"}
]';
SELECT 
    id,
    name
FROM OPENJSON(@json2)
WITH ( --虚拟表映射
    id INT '$.id',        -- 提取每个对象的id字段
    name NVARCHAR(50) '$.name'  -- 提取每个对象的name字段
);

在这里插入图片描述

简单存储过程使用示例:

下面还是通过上面的JSON字符串示例,演示一下如何存储过程使用JSON字符串接收,并在其中解析使用等。

ALTER PROCEDURE ParseStudentJson
    @json NVARCHAR(MAX)
AS
BEGIN

--json示例
--DECLARE @json NVARCHAR(MAX) = N'{
--    "student_id": 10,
--    "student_name": "张三",
--    "student_age": 18,
--    "student_class": {
--        "class_id": 2,
--        "class_code": "snj2",
--        "class_name": "三年级2班"
--    },
--    "student_subjects": [
--        {
--            "subject_id": 1,
--            "subject_name": "语文"
--        },
--        {
--            "subject_id": 2,
--            "subject_name": "数学"
--        }
--    ]
--}';

        -- 验证 JSON 格式
        IF ISJSON(@json) = 0
        BEGIN
            RAISERROR('输入参数不是有效的 JSON 格式', 16, 1);
            RETURN;
        END

     

   create table #student(
	student_id int,
	student_name varchar(50),
	student_age int
   )
  create table #student_class(
	class_id int,
	class_code varchar(50),
	class_name varchar(50),
	student_id int
   )

   create table #student_subject(
	subject_id int,
	subject_name varchar(50),
	student_id int
   )

        -- 解析学生信息 方法1
        INSERT INTO #student (student_id, student_name, student_age)
        SELECT 
        JSON_VALUE(@json, '$.student_id') AS student_id,
        JSON_VALUE(@json, '$.student_name') AS student_name,
        JSON_VALUE(@json, '$.student_age') AS student_age
	
		 /**
		 解析顶层字段 方法2
		INSERT INTO #student (student_id, student_name, student_age)
        SELECT 
            id as student_id,
            name as student_name,
            age as student_age
        FROM OPENJSON(@json) WITH (
            id INT '$.student_id',
            name NVARCHAR(50) '$.student_name',
            age INT '$.student_age'
        );
		 **/
        

        -- 解析班级信息 方法1
        INSERT INTO #student_class (class_id, class_code, class_name, student_id)
        SELECT 
		JSON_VALUE(@json, '$.student_class.class_id') AS class_id,
		JSON_VALUE(@json, '$.student_class.class_code') AS class_code,
		JSON_VALUE(@json, '$.student_class.class_name') AS class_name,
        JSON_VALUE(@json, '$.student_id') AS student_id
  

		/**
		
		  解析班级信息 方法2
        INSERT INTO #student_class (class_id, class_code, class_name, student_id)
        SELECT 
            class_id,
            class_code,
            class_name,
			student_id
        FROM OPENJSON(@json) WITH (
            class_id NVARCHAR(50) '$.student_class.class_id',
            class_code NVARCHAR(50) '$.student_class.class_code',
            class_name NVARCHAR(50) '$.student_class.class_name'
        ) AS class
        CROSS APPLY (SELECT student_id FROM #student) AS s; --CROSS APPLY​​:动态关联,右侧子查询可引用左侧表的列,类似逐行处理,有一点点类似join的感觉
		**/

		/**
		
		  解析班级信息 方法3
        INSERT INTO #student_class (class_id, class_code, class_name, student_id)
        SELECT 
			class_id,
            class_code,
            class_name,
			student_id
		FROM OPENJSON(JSON_QUERY(@json, '$.student_class')) 
		WITH (
			class_id NVARCHAR(50) '$.class_id',
			class_code NVARCHAR(50) '$.class_code',
			class_name NVARCHAR(50) '$.class_name'
		) AS class
        CROSS APPLY (SELECT student_id FROM #student) AS s; 
		**/


        -- 解析学科信息 
        INSERT INTO #student_subject (subject_id, subject_name, student_id)
        SELECT 
			subject_id,
			subject_name,
			student_id
		 FROM OPENJSON(JSON_QUERY(@json, '$.student_subjects')) 
		WITH (
			subject_id INT '$.subject_id',
			subject_name NVARCHAR(50) '$.subject_name'
		 ) AS subject
        CROSS APPLY (SELECT student_id FROM #student) AS s;
	
	--这里为了方便,只是往临时表写了数据并查出来,实际业务可以是根据入参,去更新、删除业务表数据
	select * from #student;
	select * from #student_class;
	select * from #student_subject;

	drop table #student;
	drop table #student_class;
	drop table #student_subject;
END

总结:

  • JSON_VALUE:
    • 提取标量值,如上 JSON_VALUE(@json, ‘$.student_id’)
    • 提取嵌套对象属性,如上 JSON_VALUE(@json, ‘$.student_class.class_id’)
  • JSON_QUERY:
  • 提取嵌套对象
  • 提取嵌套数组
    在这里插入图片描述
  • OPENJSON:
  • 解析JSON都要用到

网站公告

今日签到

点亮在社区的每一天
去签到