SQL Server OPENJSON 读取嵌套的 json
Posted
技术标签:
【中文标题】SQL Server OPENJSON 读取嵌套的 json【英文标题】:SQL Server OPENJSON read nested json 【发布时间】:2016-09-10 03:18:23 【问题描述】:我有一些我想在 SQL Server 2016 中解析的 json。有 Projects->Structures->Properties 的层次结构。我想编写一个解析整个层次结构的查询,但我不想通过索引号指定任何元素,即我不想做这样的事情:
openjson (@json, '$[0]')
或
openjson (@json, '$.structures[0]')
我有这样的想法,即我可以读取***项目对象的值以及表示其下方结构的 json 字符串,然后可以单独对其进行解析。问题是下面的代码不起作用:
declare @json nvarchar(max)
set @json = '
[
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Project",
"structures":[
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Structure",
"BaseStructure":"Base Structure",
"DatabaseSchema":"dbo",
"properties":[
"IdProperty":"618DC40B-4D04-4BF8-B1E6-12E13DDE86F4",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 2",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
,
"IdProperty":"FFF433EC-0BB5-41CD-8A71-B5F09B97C5FC",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 1",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
]
]
]';
select IdProject, Name, structures
from openjson (@json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max)
) as Projects
IdProject 和 Name 返回没有问题,但由于某种原因,我无法将嵌套的 json 保存在“结构”中。它只是返回 NULL,而不是 json 内容:
有谁知道这是否可行,如果可以,我做错了什么?
【问题讨论】:
【参考方案1】:使用交叉应用:
declare @json nvarchar(max)
set @json = '
[
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Project",
"structures":[
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Structure",
"BaseStructure":"Base Structure",
"DatabaseSchema":"dbo",
"properties":[
"IdProperty":"618DC40B-4D04-4BF8-B1E6-12E13DDE86F4",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 2",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
,
"IdProperty":"FFF433EC-0BB5-41CD-8A71-B5F09B97C5FC",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 1",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
]
]
]';
select
Projects.IdProject, Projects.Name as NameProject,
Structures.IdStructure, Structures.Name as NameStructure, Structures.BaseStructure, Structures.DatabaseSchema,
Properties.*
from openjson (@json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) as json
)
as Projects
cross apply openjson (Projects.structures)
with
(
IdStructure uniqueidentifier,
Name nvarchar(100),
BaseStructure nvarchar(100),
DatabaseSchema sysname,
properties nvarchar(max) as json
) as Structures
cross apply openjson (Structures.properties)
with
(
IdProperty uniqueidentifier,
NamePreoperty nvarchar(100) '$.Name',
DataType int,
[Precision] int,
[Scale] int,
IsNullable bit,
ObjectName nvarchar(100),
DefaultType int,
DefaultValue nvarchar(100)
)
as Properties
【讨论】:
我真的可以吻你,因为你发布了这个光荣的解决方案。这个答案应该是实际的解决方案,因为它是完整的。我有一个嵌套的 JSON 结构,我不知道如何访问每一层。这让我工作! 很好的解决方案。但是我有一个问题,如果某些结构没有属性,它根本不会显示该项目和结构。我如何显示项目和结构,即使它们的属性是空的,如 []? 但是使用它我如何将项目、结构和属性的数据插入到它们的相关表中。 我喜欢 OUTER APPLY 而不是 CROSS APPLY,因为外部行为就像左连接,而交叉就像可以隐藏外部查询结果的连接。 这是一个很好的答案,谢谢!【参考方案2】:如果引用 JSON 对象或数组需要指定 AS JSON 子句:
select IdProject, Name, structures
from openjson (@json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) AS JSON
) as Projects
查看常见问题解答:https://docs.microsoft.com/en-us/sql/relational-databases/json/solve-common-issues-with-json-in-sql-server?view=sql-server-ver15#return-a-nested-json-sub-object-from-json-text-with-openjson
如果你想在返回的结构数组上应用 OPENJSON,你可以使用类似下面的代码:
select IdProject, Name, structures
from openjson (@json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) AS JSON
) as Projects
CROSS APPLY OPENJSON (structures) WITH (......)
【讨论】:
【参考方案3】:典型!我在发布问题后找到了答案。指定要返回的列时需要使用“as json”关键字:
select IdProject, Name, structures
from openjson (@json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) as json
) as Projects
【讨论】:
以上是关于SQL Server OPENJSON 读取嵌套的 json的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 openjson 读取存储在 SQL Server 中的 Json 列下方?
是否可以在 SQL Server 中使用通配符作为 OPENJSON 的参数?