我正在使用 IBM Db2(版本 11.5),并且尝试查询存储在名为 data 的列中的 JSON 数据,该列包含对象数组。但是,我使用 JSON_EXISTS 的查询没有返回预期结果。
JSON结构(此处简化)包含一个数组outerField,我需要检索其中存在outerField对象且innerField等于“target”的行。但是,我使用 JSON_EXISTS 的查询没有返回预期结果。
数据列中存储的简化 JSON 数据如下所示:
{
"randomField1": "randomValue",
...
"outerField":
[
{
"innerField": "target"
},
{
"innerField": "dummy1"
},
{
"innerField": "dummy2"
}
]
}
我想使用 JSON Path,并使用在线评估工具,我发现这个查询应该可以工作:
$.outerField[?(@.innerField== "target")].
鉴于我不能直接使用 JSON_VALUE 和 json 路径,例如:
JSON_VALUE(data, '$.outerField[*].innerField') = 'target'
因为 JSON_VALUE 只需要一个值(outerField[0].innerFieldworks 如预期)。
我认为我可以使用 Db2 的 JSON_EXISTS 函数:
SELECT *
FROM test_entity
WHERE JSON_EXISTS(
data,
'$.outerField[?(@.innerField== "target")]'
)
不幸的是,即使示例 JSON 清楚地显示了outerField 中的对象,且innerField 等于“target”,也不会返回任何行。
有什么想法或建议吗?
我认为最合理的解决方案是使用 JSON_TABLE 函数取消嵌套内部数组,但我不确定如何继续。我可以在普通字段上使用 JSON_TABLE,但对于数组,我会遇到许多语法错误。例如:
SELECT *
FROM TEST_ENTITY te, JSON_TABLE(te.data, 'lax $.outerField[*]' columns (target VARCHAR(100) PATH 'lax $.innerField') ERROR ON ERROR) AS jt
WHERE jt.innerField= 'target';
此查询返回以下错误
SQL Error [42601]: An unexpected token "lax $.outerField[*]" was found following "". Expected tokens may include: "strict $".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.31.10
(即使使用严格而不是宽松,我也收到相同的错误)
SELECT * FROM test_entity
where json_exists(data, '$?(@.outerField[*].innerField == "target")') ;
考虑到我对(糟糕,非常糟糕)DB2 相关文档感到沮丧,我以一种有点“奇特”的方式管理了这项任务。
我不确定这是否是最好的解决方案,但目前有效。 我发现我可以使用 JSON_QUERY 来提取和展平 JSON 对象中的嵌套数组。
就像这样:
SELECT JSON_QUERY(tt.JSONDOC, '$.outerField[*].innerField' WITH UNCONDITIONAL WRAPPER)
FROM TEST_TABLE tt
此查询返回:
-------------------+
["targetB"] |
["target"] |
["dummy1"] |
["dummy2"] |
["target","dummy3"]|
如您所见,结果包含每行的innerField 值的扁平化CLOB。所以我意识到我可以在 WHERE 子句中使用这种方法从一开始就根据需要过滤行。
这是查询结果:
SELECT *
FROM EMPLOYEE_TABLE et
WHERE JSON_QUERY(et.JSONDOC, '$.outerField[*].innerField' WITH UNCONDITIONAL WRAPPER) LIKE '%"target"%'
这将返回至少有一个“innerField”等于“目标”值的所有行!
ID|JSONDOC |
--+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2|{"id" : 901,"firstname" : "John","lastname" : "Doe","phoneno" : "555-3762",¶ "outerField" : [{ "innerField": "target"}]} |
5|{"id" : 901,"firstname" : "John","lastname" : "Doe","phoneno" : "555-3762",¶ "outerField" : [{ "innerField": "target"},{ "innerField": "dummy3"}]}|