从 SQL 服务器中的 JSON 获取密钥名称
Get names of keys from JSON in SQL Server
我有以下 JSON。
[
{
"attributes": {
"2003": "Some text",
"2004": 0,
"2006": 0,
"2008": 0,
"2011": 0,
"2120": 0
},
"path": "/Path1",
"changeDate": "2019-11-11T13:56:37.987Z",
"guid": "00000000-0000-0000-0000-000000000000",
"version": 0,
"timestamp": "2019-11-11T14:21:14.86427Z"
},
{
"attributes": {
"2121": 0,
"2297": 0,
"2298": 0,
"2299": 0,
"2805": 0,
"8501": 0,
"12004": 0,
"13266": 0,
"13282": 0
},
"path": "P:/Path2/SubPath",
"changeDate": "2019-11-11T13:55:35.943Z",
"guid": "705b30ab-53b0-42ee-bb98-6d80daae2e18",
"version": 1,
"timestamp": "2019-11-11T09:08:54.417Z"
},
{
"attributes": {},
"path": "PP:/OneMorePath",
"changeDate": "2019-11-11T14:20:49.5Z",
"guid": "b9aac8f3-1f2a-4b52-b8d8-af6b654d3f0f",
"version": 41,
"timestamp": "2019-11-11T13:26:24.723Z"
}
]
为此,我有两个 SQL 服务器表。
CREATE TABLE [dbo].[Foo]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT(NEWID()),
[Path] NVARCHAR(128) NOT NULL,
[ChangeDate] DATETIME NOT NULL,
[Guid] UNIQUEIDENTIFIER NOT NULL,
[Version] INT NOT NULL,
[Timestamp] DATETIME NOT NULL
)
CREATE TABLE [dbo].[FooAttributes]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT(NEWID()),
[IdFoo] UNIQUEIDENTIFIER NOT NULL,
[Key] INT NOT NULL,
[Value] NVARCHAR(255) NOT NULL
)
头数据我可以在SQL服务器中查询。
SELECT *
FROM OPENJSON(@Json)
WITH (
[Path] NVARCHAR(128) 'strict $.path',
[ChangeDate] DATETIME2 '$.changeDate',
[Guid] UNIQUEIDENTIFIER '$.guid',
[Version] INT '$.version',
[Timestamp] DATETIME2 '$.timestamp'
)
为此我得到了这个结果。
Path | ChangeDate | Guid | Version | Timestamp
------------------------------------------------------------------------------------------------------------------------------------------------
/Path1 | 2019-11-11 13:56:37.9870000 | 00000000-0000-0000-0000-000000000000 | 0 | 2019-11-11 14:21:14.8642700
P:/Path2/SubPath | 2019-11-11 13:55:35.9430000 | 705B30AB-53B0-42EE-BB98-6D80DAAE2E18 | 1 | 2019-11-11 09:08:54.4170000
PP:/OneMorePath | 2019-11-11 14:20:49.5000000 | B9AAC8F3-1F2A-4B52-B8D8-AF6B654D3F0F | 41 | 2019-11-11 13:26:24.7230000
没关系。但是我找不到任何查询属性的可能性,因为这不是 key/value 对的数组,而是具有值的字段。
IdFoo | AttributeName | AttributeValue
---------------------------------------
<IdFoo1> | 2003 | Some text
<IdFoo1> | 2004 | 0
<IdFoo1> | 2006 | 0
<IdFoo1> | 2008 | 0
<IdFoo1> | 2011 | 0
<IdFoo1> | 2120 | 0
<IdFoo2> | 2121 | 0
<IdFoo2> | 2297 | 0
<IdFoo2> | 2298 | 0
<IdFoo2> | 2299 | 0
<IdFoo2> | 2805 | 0
<IdFoo2> | 8501 | 0
<IdFoo2> | 12004 | 0
<IdFoo2> | 13266 | 0
<IdFoo2> | 13282 | 0
在 SQL Server 2016 中是否可以根据需要获得此子结构?
您需要使用 AS JSON
使用显式模式解析输入 JSON
数组,以指定 $attributes
属性 包含内部 JSON
对象。之后,您需要将额外的 CROSS APPLY
运算符与另一个 OPENJSON()
调用一起使用默认模式(没有 WITH
子句),即 returns 一个 table 和 [= 20=、value
和 type
列。
JSON:
DECLARE @json nvarchar(max) = N'[
{
"attributes": {
"2003": "Some text",
"2004": 0,
"2006": 0,
"2008": 0,
"2011": 0,
"2120": 0
},
"path": "/Path1",
"changeDate": "2019-11-11T13:56:37.987Z",
"guid": "00000000-0000-0000-0000-000000000000",
"version": 0,
"timestamp": "2019-11-11T14:21:14.86427Z"
},
{
"attributes": {
"2121": 0,
"2297": 0,
"2298": 0,
"2299": 0,
"2805": 0,
"8501": 0,
"12004": 0,
"13266": 0,
"13282": 0
},
"path": "P:/Path2/SubPath",
"changeDate": "2019-11-11T13:55:35.943Z",
"guid": "705b30ab-53b0-42ee-bb98-6d80daae2e18",
"version": 1,
"timestamp": "2019-11-11T09:08:54.417Z"
},
{
"attributes": {},
"path": "PP:/OneMorePath",
"changeDate": "2019-11-11T14:20:49.5Z",
"guid": "b9aac8f3-1f2a-4b52-b8d8-af6b654d3f0f",
"version": 41,
"timestamp": "2019-11-11T13:26:24.723Z"
}
]'
声明:
SELECT
j1.Guid,
j2.[key] AS AttrName,
j2.[value] AS AttrValue
FROM OPENJSON(@json, '$') WITH (
Guid UNIQUEIDENTIFIER '$.guid',
-- other columns definitions
attributes nvarchar(max) '$.attributes' AS JSON
) j1
CROSS APPLY OPENJSON(j1.attributes) j2
结果:
Guid AttrName AttrValue
00000000-0000-0000-0000-000000000000 2003 Some text
00000000-0000-0000-0000-000000000000 2004 0
00000000-0000-0000-0000-000000000000 2006 0
00000000-0000-0000-0000-000000000000 2008 0
00000000-0000-0000-0000-000000000000 2011 0
00000000-0000-0000-0000-000000000000 2120 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2121 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2297 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2298 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2299 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2805 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 8501 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 12004 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 13266 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 13282 0
使用 As Json
和 Cross apply
以及另一个 OpenJson
可以得到你想要的结果:
SELECT [Guid], [key], [value]
FROM OPENJSON(@Json)
WITH (
[Guid] UNIQUEIDENTIFIER '$.guid',
[Attributes] NVARCHAR(max) '$.attributes' As Json
)
CROSS APPLY OPENJSON(Attributes)
注意 key
是 nvarchar(4000)
而 value
是 nvarchar(max)
。
上观看现场演示
我有以下 JSON。
[
{
"attributes": {
"2003": "Some text",
"2004": 0,
"2006": 0,
"2008": 0,
"2011": 0,
"2120": 0
},
"path": "/Path1",
"changeDate": "2019-11-11T13:56:37.987Z",
"guid": "00000000-0000-0000-0000-000000000000",
"version": 0,
"timestamp": "2019-11-11T14:21:14.86427Z"
},
{
"attributes": {
"2121": 0,
"2297": 0,
"2298": 0,
"2299": 0,
"2805": 0,
"8501": 0,
"12004": 0,
"13266": 0,
"13282": 0
},
"path": "P:/Path2/SubPath",
"changeDate": "2019-11-11T13:55:35.943Z",
"guid": "705b30ab-53b0-42ee-bb98-6d80daae2e18",
"version": 1,
"timestamp": "2019-11-11T09:08:54.417Z"
},
{
"attributes": {},
"path": "PP:/OneMorePath",
"changeDate": "2019-11-11T14:20:49.5Z",
"guid": "b9aac8f3-1f2a-4b52-b8d8-af6b654d3f0f",
"version": 41,
"timestamp": "2019-11-11T13:26:24.723Z"
}
]
为此,我有两个 SQL 服务器表。
CREATE TABLE [dbo].[Foo]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT(NEWID()),
[Path] NVARCHAR(128) NOT NULL,
[ChangeDate] DATETIME NOT NULL,
[Guid] UNIQUEIDENTIFIER NOT NULL,
[Version] INT NOT NULL,
[Timestamp] DATETIME NOT NULL
)
CREATE TABLE [dbo].[FooAttributes]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT(NEWID()),
[IdFoo] UNIQUEIDENTIFIER NOT NULL,
[Key] INT NOT NULL,
[Value] NVARCHAR(255) NOT NULL
)
头数据我可以在SQL服务器中查询。
SELECT *
FROM OPENJSON(@Json)
WITH (
[Path] NVARCHAR(128) 'strict $.path',
[ChangeDate] DATETIME2 '$.changeDate',
[Guid] UNIQUEIDENTIFIER '$.guid',
[Version] INT '$.version',
[Timestamp] DATETIME2 '$.timestamp'
)
为此我得到了这个结果。
Path | ChangeDate | Guid | Version | Timestamp
------------------------------------------------------------------------------------------------------------------------------------------------
/Path1 | 2019-11-11 13:56:37.9870000 | 00000000-0000-0000-0000-000000000000 | 0 | 2019-11-11 14:21:14.8642700
P:/Path2/SubPath | 2019-11-11 13:55:35.9430000 | 705B30AB-53B0-42EE-BB98-6D80DAAE2E18 | 1 | 2019-11-11 09:08:54.4170000
PP:/OneMorePath | 2019-11-11 14:20:49.5000000 | B9AAC8F3-1F2A-4B52-B8D8-AF6B654D3F0F | 41 | 2019-11-11 13:26:24.7230000
没关系。但是我找不到任何查询属性的可能性,因为这不是 key/value 对的数组,而是具有值的字段。
IdFoo | AttributeName | AttributeValue
---------------------------------------
<IdFoo1> | 2003 | Some text
<IdFoo1> | 2004 | 0
<IdFoo1> | 2006 | 0
<IdFoo1> | 2008 | 0
<IdFoo1> | 2011 | 0
<IdFoo1> | 2120 | 0
<IdFoo2> | 2121 | 0
<IdFoo2> | 2297 | 0
<IdFoo2> | 2298 | 0
<IdFoo2> | 2299 | 0
<IdFoo2> | 2805 | 0
<IdFoo2> | 8501 | 0
<IdFoo2> | 12004 | 0
<IdFoo2> | 13266 | 0
<IdFoo2> | 13282 | 0
在 SQL Server 2016 中是否可以根据需要获得此子结构?
您需要使用 AS JSON
使用显式模式解析输入 JSON
数组,以指定 $attributes
属性 包含内部 JSON
对象。之后,您需要将额外的 CROSS APPLY
运算符与另一个 OPENJSON()
调用一起使用默认模式(没有 WITH
子句),即 returns 一个 table 和 [= 20=、value
和 type
列。
JSON:
DECLARE @json nvarchar(max) = N'[
{
"attributes": {
"2003": "Some text",
"2004": 0,
"2006": 0,
"2008": 0,
"2011": 0,
"2120": 0
},
"path": "/Path1",
"changeDate": "2019-11-11T13:56:37.987Z",
"guid": "00000000-0000-0000-0000-000000000000",
"version": 0,
"timestamp": "2019-11-11T14:21:14.86427Z"
},
{
"attributes": {
"2121": 0,
"2297": 0,
"2298": 0,
"2299": 0,
"2805": 0,
"8501": 0,
"12004": 0,
"13266": 0,
"13282": 0
},
"path": "P:/Path2/SubPath",
"changeDate": "2019-11-11T13:55:35.943Z",
"guid": "705b30ab-53b0-42ee-bb98-6d80daae2e18",
"version": 1,
"timestamp": "2019-11-11T09:08:54.417Z"
},
{
"attributes": {},
"path": "PP:/OneMorePath",
"changeDate": "2019-11-11T14:20:49.5Z",
"guid": "b9aac8f3-1f2a-4b52-b8d8-af6b654d3f0f",
"version": 41,
"timestamp": "2019-11-11T13:26:24.723Z"
}
]'
声明:
SELECT
j1.Guid,
j2.[key] AS AttrName,
j2.[value] AS AttrValue
FROM OPENJSON(@json, '$') WITH (
Guid UNIQUEIDENTIFIER '$.guid',
-- other columns definitions
attributes nvarchar(max) '$.attributes' AS JSON
) j1
CROSS APPLY OPENJSON(j1.attributes) j2
结果:
Guid AttrName AttrValue
00000000-0000-0000-0000-000000000000 2003 Some text
00000000-0000-0000-0000-000000000000 2004 0
00000000-0000-0000-0000-000000000000 2006 0
00000000-0000-0000-0000-000000000000 2008 0
00000000-0000-0000-0000-000000000000 2011 0
00000000-0000-0000-0000-000000000000 2120 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2121 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2297 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2298 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2299 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 2805 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 8501 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 12004 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 13266 0
705b30ab-53b0-42ee-bb98-6d80daae2e18 13282 0
使用 As Json
和 Cross apply
以及另一个 OpenJson
可以得到你想要的结果:
SELECT [Guid], [key], [value]
FROM OPENJSON(@Json)
WITH (
[Guid] UNIQUEIDENTIFIER '$.guid',
[Attributes] NVARCHAR(max) '$.attributes' As Json
)
CROSS APPLY OPENJSON(Attributes)
注意 key
是 nvarchar(4000)
而 value
是 nvarchar(max)
。