MS SQL 查询包含 JSON 的字段

MS SQL Query a field containing JSON

我在 table 的 SQL 字段中有以下 JSON:

{
   "type": "info",
   "date": "2019/11/12 14:28:51",
    "state": {
        "6ee8587f-3b8c-4e5c-89a9-9f04752607f0": {
            "state": "open",
            "color": "#0000ff"
        }
    },
...
}

我在 MS SQL 中使用以下查询:

SELECT 
     JSON_VALUE(json_data, '$.type') AS msg_type
    ,JSON_VALUE(json_data, '$."date"') AS event_date
    ,JSON_QUERY(json_data, '$.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0".state') AS json_state
    ,JSON_QUERY(json_data, '$.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0".color') AS json_color
FROM 
[dbo].[tbl_json_dump]

要取回日期(保留字),我必须将字段名称放在 $."date"

我似乎无法取回状态或颜色字段的数据,我认为这与它嵌套在“6ee8587f-3b8c-4e5c-89a9-9f04752607f0”下有关,因为当我查询时:

JSON_QUERY(json_data, '$.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0"') AS json_state

我拿回了对象 -

{"state":"open","color":"#0000ff"}

但使用

JSON_QUERY(json_data, '$.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0".state') AS json_state

它不起作用

对我做错了什么有什么建议吗??

只需将 JSON_QUERY 替换为 JSON_VALUE,因为您有兴趣获取该值。


JSON_QUERY 应该是 return 一个 JSON 片段,旨在处理对象和数组,而不是值。

您可以尝试另一种可能的方法(更复杂),它解析所有嵌套的 JSON 对象。

Table:

CREATE TABLE Data (
   JsonData nvarchar(max)
)
INSERT INTO Data
   (JsonData)
VALUES 
   (N'{
   "type": "info",
   "date": "2019/11/12 14:28:51",
    "state": {
        "6ee8587f-3b8c-4e5c-89a9-9f04752607f0": {
            "state": "open",
            "color": "#0000ff"
        },
        "6ee8587f-3b8c-4e5c-89a9-9f04752607f1": {
            "state": "open",
            "color": "#0000ff"
        }
    }
}')

声明:

SELECT 
   j1.[type], j1.[date], j2.[key], j3.state, j3.color
FROM Data d
CROSS APPLY OPENJSON(d.JsonData) WITH (
   [type] nvarchar(100) '$.type',
   [date] datetime '$.date',
   [state] nvarchar(max) '$.state' AS JSON
) j1
CROSS APPLY OPENJSON(j1.state) j2
CROSS APPLY OPENJSON(j2.[value]) WITH (
   state nvarchar(10) '$.state',
   color nvarchar(10) '$.color'
) j3

结果:

type    date                key                                     state   color
info    12/11/2019 14:28:51 6ee8587f-3b8c-4e5c-89a9-9f04752607f0    open    #0000ff
info    12/11/2019 14:28:51 6ee8587f-3b8c-4e5c-89a9-9f04752607f1    open    #0000ff

备注:

如果输入 JSON"state" JSON 对象中只有一个键 "6ee8587f-3b8c-4e5c-89a9-9f04752607f0",您可以使用正确的 JSON_VALUE() 获取值路径 $.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0".state.

Salman A 已经给出了答案。补充几点。

JSON_VALUE() - 提取标量值

JSON_QUERY() - 从 JSON 字符串中提取对象或数组。

如果您看到语法,JSON_QUERY ( expression [ , path ] )JSON_VALUE ( expression , path ),除了 path[] 方括号外,两者或多或少都是可选的。这是因为 JSON_QUERY() 可以根据需要提取整个 JSON 字段。

并且在 return 类型上,

JSON_VALUE() returns JSON 类型 nvarchar(max)

的片段

JSON_QUERY() returns 类型为 nvarchar(4000)

的单个文本值

整体比较

DECLARE @data NVARCHAR(4000)
SET @data=N'{
    "type": "info",
   "date": "2019/11/12 14:28:51",
    "state": {
        "6ee8587f-3b8c-4e5c-89a9-9f04752607f0": {
            "state": "open",
            "color": "#0000ff"
        }
    },
}'
 SELECT 
   JSON_VALUE(@data,'$.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0"') AS 'JSON_VALUE_FAILED',
   JSON_QUERY(@data,'$.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0"') AS 'JSON_QUERY_SUCCEED',
   JSON_VALUE(@data,'$.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0".state') AS 'JSON_VALUE_SUCCEED',
   JSON_QUERY(@data,'$.state."6ee8587f-3b8c-4e5c-89a9-9f04752607f0".state') AS 'JSON_QUERY_SUCCEED';

Check Output here