甲骨文 JSON 查询

Posted

技术标签:

【中文标题】甲骨文 JSON 查询【英文标题】:Oracle JSON query 【发布时间】:2021-04-28 17:21:21 【问题描述】:

我有一个 JSON 列,它在 people 表上存储人们在他们访问过的国家所做的最佳活动......


  "countries": [
    
      "name": "Ireland",
      "bestActivity": 
        "name": "Drinking"
      
    ,
    
      "name": "Scotland",
      "bestActivity": 
        "name": "Dancing"
      
    
  ]

其他人可能是:


  "countries": [
    
      "name": "Ireland",
      "bestActivity": 
        "name": "Football"
      
        ,
    
      "name": "England",
      "bestActivity": 
        "name": "Golf"
      
        
  ]

我想选择所有访问过爱尔兰并且在爱尔兰饮酒活动最好的人,以及访问过苏格兰并且饮酒活动最好的人。

真的很挣扎。有什么建议吗?

【问题讨论】:

【参考方案1】:

您可以使用JSON_EXISTS 函数根据您描述的条件过滤您的表格。我使用您在问题中提供的 JSON 结构在下面构建了一个示例查询。

WITH
    sample_table (first_name, json_col)
    AS
        (SELECT 'John', '
     "countries": [
         
            "name": "Ireland",
            "bestActivity" : 
                 "name": "Drinking"
             , 
        ,
         
            "name": "Scotland",
            "bestActivity" : 
                  "name": "Dancing"
             
        
 ' FROM DUAL
         UNION ALL
         SELECT 'Jane', '
     "countries": [
         
            "name": "Ireland",
            "bestActivity" : 
                 "name": "Football"
             , 
        ,
         
            "name": "England",
            "bestActivity" : 
                  "name": "Golf"
             
        
 ' FROM DUAL)
SELECT *
  FROM sample_table s
 WHERE     JSON_EXISTS (s.json_col, '$.countries[*]?(@.name == "Scotland")')
       AND JSON_EXISTS (
               s.json_col,
               '$.countries[*]?(@.name == "Ireland" && @.bestActivity.name == "Drinking")');

【讨论】:

【参考方案2】:

您可以使用JSON_TABLE() 函数,因为您的数据库版本是12c适用于所有子版本),例如

SELECT first_name
  FROM t,   
  JSON_TABLE(jscol, '$.countries[*]' 
       COLUMNS ( 
                country      VARCHAR2(90) PATH '$.name',  
                bestActivity VARCHAR2(90) PATH '$.bestActivity.name'
               )
            )
 WHERE (country = 'Ireland' AND bestActivity = 'Drinking')
    OR  country = 'Scotland'
 GROUP BY first_name
 HAVING COUNT(*)>1

Demo

你可以使用JSON_EXISTS()函数是数据库版本是12cR2+这样的格式

SELECT first_name
  FROM t
 WHERE JSON_EXISTS(jscol,
                    '$.countries?(@.name == "Ireland"
                               && @.bestActivity.name == "Drinking")')
   AND JSON_EXISTS(jscol,                            
                    '$.countries?(@.name == "Scotland")');

Demo

请注意,当使用SQL*Plus 时,应在发出SET DEFINE OFF 后调用查询,以防止&& 操作数被解释为替换变量。

【讨论】:

以上是关于甲骨文 JSON 查询的主要内容,如果未能解决你的问题,请参考以下文章

为啥 SELECT 查询不启动事务? [甲骨文]

有啥方法可以优化这个查询?甲骨文 11g

为啥当我的子查询无效时,此 SQL 查询会起作用? - 甲骨文 [重复]

如何在查询中使用别名字段? (甲骨文10g)

甲骨文。查询中的参数。变量的名称/编号错误[关闭]

甲骨文。无法理解 FOR 如何与子查询 SELECT INTO 一起使用