如何将嵌套JSON中的数据保存到SQL Server的关联表中
没问题!既然你已经成功把嵌套JSON解析成了关系型数据格式,接下来要把这些数据插入到关联的Project、SubSection、Items表中,核心要注意外键依赖的插入顺序和空节点的过滤处理,我给你整理了一套完整的分步方案:
解决方案:分步插入关联表数据
因为三个表存在外键依赖(SubSection依赖Project的IdProject,Items依赖SubSection的IdStructure),所以必须按「Project → SubSection → Items」的顺序插入,同时要处理JSON里存在的空节点(比如第三个项目的空SubSection、第四个项目的缺失Items)。
1. 先插入Project表
从解析后的JSON中提取唯一的项目数据,避免重复插入:
INSERT INTO Project (IdProject, Name) SELECT DISTINCT Projects.IdProject, Projects.Name FROM openjson (@json) with ( IdProject int, Name nvarchar(100), SubSection nvarchar(max) as json ) as Projects -- 可选:如果表中已有相同IdProject,跳过重复数据 WHERE NOT EXISTS (SELECT 1 FROM Project WHERE IdProject = Projects.IdProject);
2. 再插入SubSection表
关联已插入的Project表,同时过滤掉JSON中空的SubSection节点:
INSERT INTO SubSection (IdStructure, IdProject, Name) SELECT DISTINCT Structures.IdStructure, Projects.IdProject, Structures.Name FROM openjson (@json) with ( IdProject int, SubSection nvarchar(max) as json ) as Projects OUTER APPLY openjson (Projects.SubSection) with ( IdStructure int, Name nvarchar(100) ) as Structures -- 过滤掉空的SubSection节点(IdStructure为NULL的情况) WHERE Structures.IdStructure IS NOT NULL -- 可选:跳过已存在的SubSection数据 AND NOT EXISTS (SELECT 1 FROM SubSection WHERE IdStructure = Structures.IdStructure);
3. 最后插入Items表
关联已插入的SubSection表,处理Items节点缺失的情况:
INSERT INTO Items (IdProperty, IdStructure, Name, DataType, [Precision], [Scale], IsNullable, ObjectName, DefaultType, DefaultValue) SELECT DISTINCT Properties.IdProperty, Structures.IdStructure, Properties.NamePreoperty, Properties.DataType, Properties.[Precision], Properties.[Scale], Properties.IsNullable, Properties.ObjectName, Properties.DefaultType, Properties.DefaultValue FROM openjson (@json) with ( IdProject int, SubSection nvarchar(max) as json ) as Projects OUTER APPLY openjson (Projects.SubSection) with ( IdStructure int, Items nvarchar(max) as json ) as Structures -- 当Items节点不存在时,转为空数组避免OPENJSON报错 OUTER APPLY openjson (ISNULL(Structures.Items, '[]')) with ( IdProperty int, NamePreoperty nvarchar(100) '$.Name', DataType int, [Precision] int, [Scale] int, IsNullable bit, ObjectName nvarchar(100), DefaultType int, DefaultValue nvarchar(100) ) as Properties -- 过滤掉空的Items节点(IdProperty为NULL的情况) WHERE Properties.IdProperty IS NOT NULL -- 可选:跳过已存在的Items数据 AND NOT EXISTS (SELECT 1 FROM Items WHERE IdProperty = Properties.IdProperty);
额外优化建议
- 事务包裹:如果要确保三个表的插入操作原子性(要么全成功,要么全失败),可以把所有插入语句放在事务里:
BEGIN TRANSACTION; BEGIN TRY -- 插入Project的语句 -- 插入SubSection的语句 -- 插入Items的语句 COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; THROW; -- 抛出错误信息,方便排查问题 END CATCH;
- 重复数据处理:上面的
WHERE NOT EXISTS子句是为了避免插入重复的主键数据,如果你的表主键是自增类型,或者业务允许重复(不推荐),可以去掉这些判断。 - 空值兼容:
ISNULL(Structures.Items, '[]')的作用是当JSON里没有Items节点时,给OPENJSON一个空数组,避免出现解析错误。
内容的提问来源于stack exchange,提问作者Sunny
相关产品推荐
相关产品推荐

