我有一个看起来像这样的传入数据结构:
declare @json nvarchar(max) = '{
"action": "edit",
"data": {
"2077-09-02": {
"Description": "some stuff",
"EffectDate": "2077-1-1"
}
}
}';
长话短说,我认为TSQL讨厌这种json结构,因为无论我尝试了什么,除“ action”外,我无法获得任何其他值。
{data}对象包含另一个对象{2077-09-02}。 “ 2077-09-02” 总是不同的。我不能指望那会是什么日期。
这有效:
select json_value(@json, '$.action');
尝试获取其他值时,没有有效。
select json_value(@json, '$.data'); --returns null
select json_value(@json, '$.data[0]'); --returns null
select json_value(@json, 'lax $.data.[2077-09-02].Description');
--JSON path is not properly formatted. Unexpected character '[' is found at position 11.
select json_value(@json, 'lax $.data.2077-09-02.Description');
--JSON path is not properly formatted. Unexpected character '2' is found at position 11.
如何获得其他值? JSON对于TSQL来说还不够完善吗?
答案 0 :(得分:1)
使用双引号代替[]
。 JSON Path使用JavaScript的约定,其中字符串用双引号引起来。文档的示例包含此路径$."first name"
。
在这种情况下:
select json_value(@json,'$.data."2077-09-02".Description');
返回:
some stuff
对于其他调用,JSON_VALUE仅可以返回标量值,而不能返回对象。您需要使用JSON_QUERY提取JSON对象,例如:
select json_query(@json,'$.data."2077-09-02"');
返回:
{
"Description": "some stuff",
"EffectDate": "2077-1-1"
}
答案 1 :(得分:1)
将基于文本的容器的声明部分用作数据绝不是一个好主意。 "2077-09-02"
是有效的json键,但很难查询。
您可以尝试以下方法:
declare @json nvarchar(max) = '{
"action": "edit",
"data": {
"2077-09-02": {
"Description": "some stuff",
"EffectDate": "2077-1-1"
}
}
}';
SELECT A.[action]
,B.[key] AS DateValue
,C.*
FROM OPENJSON(@json)
WITH([action] NVARCHAR(100)
,[data] NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.[data]) B
CROSS APPLY OPENJSON(B.[value])
WITH (Description NVARCHAR(100)
,EffectDate DATE) C;
结果
action DateValue Description EffectDate
edit 2077-09-02 some stuff 2077-01-01
想法:
OPENJSON
将返回action
和data
。 WITH
子句告诉引擎,action
是一个简单值,而data
是嵌套的JSON OPENJSON
进入data
B.[key]
来获取json键的值OPENJSON
来进入 {1>}内部的列。但是:如果此JSON受您控制,建议您更改其结构。