TSQL——为子对象(不是数组)中的未知/动态键提取JSON值
我正在使用DataTables、DataTables编辑器、JavaScript和MSSQL 2016 我想在SQL Server中解析此字符串:TSQL——为子对象(不是数组)中的未知/动态键提取JSON值,json,sql-server,tsql,Json,Sql Server,Tsql,我正在使用DataTables、DataTables编辑器、JavaScript和MSSQL 2016 我想在SQL Server中解析此字符串: { "action":"edit", "data": { "2019-08-03":{ "Description":"sdfsafasdfasdf", "FirstFroz
{
"action":"edit",
"data": {
"2019-08-03":{
"Description":"sdfsafasdfasdf",
"FirstFrozenStep":"333"
}
}
}
{
"action":"edit",
"DT_RowId":"2019-08-03",
"Description":"sdfsafasdfasdf",
"FirstFrozenStep":"333"
}
我不知道如何访问密钥“2019-08-03”。这表示数据表编辑器中的主键或DT_RowId
。它是动态的。。。它可能会改变
历史上,我只是将JavaScript中的数据处理为平面对象,这在SQL Server中更容易解析:
{
"action":"edit",
"data": {
"2019-08-03":{
"Description":"sdfsafasdfasdf",
"FirstFrozenStep":"333"
}
}
}
{
"action":"edit",
"DT_RowId":"2019-08-03",
"Description":"sdfsafasdfasdf",
"FirstFrozenStep":"333"
}
但是,我想知道如何使用json\u query
、json\u value
和openjson()
深入到上面提到的“动态”键,然后访问其值
以下是我所有失败的尝试:
declare
@jsonRequest nvarchar(max) = '{"action":"edit","data":{"2019-08-03":{"Description":"sdfsafasdfasdf","FirstFrozenStep":"333"}}}'
,@json2 nvarchar(max) = '{"2019-08-03":{"Description":"sdfsafasdfasdf","FirstFrozenStep":"333"}}'
,@jsonEASY nvarchar(max) = '{"action":"edit","DT_RowId":"2019-08-03","Description":"sdfsafasdfasdf","FirstFrozenStep":"333"}'
select
json_value(@jsonRequest, '$.action') as [action]
--,json_value(@jsonRequest, '$.data.[0]') as [action]
--,json_query(@jsonRequest, '$.data[0]')
--,json_query(@jsonRequest, '$.data.[0]')
--,json_query(@jsonRequest, '$.data[0].Description')
--,json_query(@jsonRequest, '$.data.Description')
--,json_query(@jsonRequest, '$.data.[0].Description')
select
[Key]
,Value
,Type
--,json_query(value, '$')
from
openjson(@jsonRequest)
SELECT x.[Key], x.[Value]
FROM OPENJSON(@jsonRequest, '$') AS x;
select
x.[Key]
,x.[Value]
--,json_query(x.value, '$')
--,(select * from openjson(x.value))
FROM OPENJSON(@jsonRequest, '$') AS x;
SELECT x.[Key], x.[Value]
FROM OPENJSON(@json2, '$') AS x;
select
json_value(@jsonEASY, '$.action') as [action]
,json_value(@jsonEASY, '$.DT_RowId') as [DT_RowId]
,json_value(@jsonEASY, '$.Description') as [Description]
您可以使用OUTER APPLY进入JSON的下一个级别:
SELECT L1.[key], L2.[key], L2.[value]
FROM openjson(@json,'$.data') AS L1
OUTER APPLY openjson(L1.[value]) AS L2
它将返回:
key key value
2019-08-03 Description sdfsafasdfasdf
2019-08-03 FirstFrozenStep 333
您可以使用OUTER APPLY进入JSON的下一个级别:
SELECT L1.[key], L2.[key], L2.[value]
FROM openjson(@json,'$.data') AS L1
OUTER APPLY openjson(L1.[value]) AS L2
它将返回:
key key value
2019-08-03 Description sdfsafasdfasdf
2019-08-03 FirstFrozenStep 333
最明确和类型安全的方法可能是: 我用两个动态键定义JSON --询问
SELECT A.[action]
,B.[key]
,C.*
FROM OPENJSON(@json) WITH([action] NVARCHAR(100)
,[data] NVARCHAR(MAX) AS JSON) A
OUTER APPLY OPENJSON(A.[data]) B
OUTER APPLY OPENJSON(B.[value]) WITH([Description] NVARCHAR(100)
,FirstFrozenStep INT) C;
结果
action key Description FirstFrozenStep
edit 2019-08-03 sdfsafasdfasdf 333
edit 2019-08-04 blah4 444
简而言之:
- 第一个
将返回别名OPENJSON()
下的两个一级键。A
元素以JSON的形式返回数据
,允许以后继续此操作
- 第二个
OPENJSON()
- 第三个
现在将OPENJSON()
作为输入B.[value]
WITH
-子句允许读取隐式旋转并键入的内部元素
一般情况下:在通用数据容器中,使用描述性部分作为内容并不是一个好主意。这是可能的,看起来可能很聪明,但最好将日期作为内容放在
日期
键中 最明确和类型安全的方法可能是:
我用两个动态键定义JSON
--询问
SELECT A.[action]
,B.[key]
,C.*
FROM OPENJSON(@json) WITH([action] NVARCHAR(100)
,[data] NVARCHAR(MAX) AS JSON) A
OUTER APPLY OPENJSON(A.[data]) B
OUTER APPLY OPENJSON(B.[value]) WITH([Description] NVARCHAR(100)
,FirstFrozenStep INT) C;
结果
action key Description FirstFrozenStep
edit 2019-08-03 sdfsafasdfasdf 333
edit 2019-08-04 blah4 444
简而言之:
- 第一个
将返回别名OPENJSON()
下的两个一级键。A
元素以JSON的形式返回数据
,允许以后继续此操作
- 第二个
OPENJSON()
- 第三个
现在将OPENJSON()
作为输入B.[value]
WITH
-子句允许读取隐式旋转并键入的内部元素
一般情况下:在通用数据容器中,使用描述性部分作为内容并不是一个好主意。这是可能的,看起来可能很聪明,但最好将日期作为内容放在
日期
键中 我收到这样的消息:“关键字“with”附近的语法不正确。如果此语句是公共表表达式、xmlnamespaces子句或更改跟踪上下文子句,则前一个语句必须以分号终止。”@raydlevel5,但不是因为OPENJSON语句中的with。这一定是其他东西…对不起,我执行时附加到一个数据库有错误的“版本”。。。我会回来报到的。谢谢。我接受你的答案,因为它是有效的,你已经解释了一个工具,我可以在未来使用(外部应用)。我完全同意你反对使用通用密钥的说法;但是,您看到的请求是“原始”的,由DataTables编辑器生成。因为我可以选择在请求到达SQL之前对其进行操作,所以我可能会继续“扁平化”数据以使其更易于解析。。。。但是你已经为我们提供了一种获得通用密钥的方法@raydlevel5还有一个反对内容键的理由:它们在任何情况下都是nvarchar。普通内容是以键入的方式(例如,通过格式化日期的方式)输入的,您可以以类型安全的方式阅读。我收到以下消息:“关键字“with”附近的语法不正确。如果此语句是公共表表达式、xmlnamespaces子句或更改跟踪上下文子句,则前一条语句必须以分号终止。“@raydlevel5,但不是因为OPENJSON语句中的with。这一定是其他原因……抱歉,我在附加到“版本”错误的数据库时执行了此语句"... 我会回来报到的。谢谢。我接受你的答案,因为它是有效的,你已经解释了一个工具,我可以在未来使用(外部应用)。我完全同意你反对使用通用密钥的说法;但是,您看到的请求是“原始”的,由DataTables编辑器生成。因为我可以选择在请求到达SQL之前对其进行操作,所以我可能会继续“扁平化”数据以使其更易于解析。。。。但是你已经为我们提供了一种获得通用密钥的方法@raydlevel5还有一个反对内容键的理由:它们在任何情况下都是nvarchar。普通内容是以键入的方式(例如,通过格式化日期的方式)输入的,您可以以类型安全的方式读取。