【问题标题】:How can I get value with key in JSON_DATAGUIDE (dynamically)如何使用 JSON_DATAGUIDE 中的键获得价值(动态)
【发布时间】:2021-09-17 07:29:42
【问题描述】:

JSON_DATAGUIDE 只给我键而不是像 "$.a" 这样的值。我怎样才能得到下面这个例子的键值对。

select json_dataguide('{a:100, b:200, c:300}')
from   dual;

JSON_DATAGUIDE('{A:100,B:200,C:300}')                                           
--------------------------------------------------------------------------------
[{"o:path":"$.a","type":"number","o:length":4},{"o:path":"$.b","type":"number","
o:length":4},{"o:path":"$.c","type":"number","o:length":4}]

我需要这样的表格:

Column Key, Column Value
    a           100
    b           200
    c           300

我想在不使用declarebegin 等的情况下找到它。只有内置​​函数,例如json_tablejson_dataguide。我不想声明函数什么的。

【问题讨论】:

    标签: sql json oracle parsing


    【解决方案1】:

    另一种选择是

    declare
      j  JSON_OBJECT_T;
      i  NUMBER;
      k  JSON_KEY_LIST;
      CURSOR c_json IS
         SELECT '{a:100, b:200, c:300}' as myJsonCol from dual;
    begin
      FOR rec IN c_json
      LOOP
         j := JSON_OBJECT_T.parse(rec.myJsonCol);
         k := j.get_keys;
         dbms_output.put_line('KEY VAL');
         FOR i in 1..k.COUNT
         LOOP
            dbms_output.put_line(k(i) || ' ' || j.get_Number(k(i)));
         END LOOP;
       END LOOP;
    END;
    /
    

    演示

    db<>fiddle

    然后您可以将结果存储在sys_refcursor 中,甚至可以创建一个表函数。

    【讨论】:

    • 我想在不使用declare、begin等的情况下找到它。只有内置​​函数,例如json_table、json_dataguide。我不想声明函数什么的。
    • 例如,json_table(json_dataguide, '$[*]' COLUMNS (keys VARCHAR2(128 CHAR) PATH '$."o:path"')) 给了我钥匙。
    • @samurai-jack07,这就是为什么我在答案的开头说它只是一种选择。您可以基于它构建自定义函数。我希望其他人可以找到一种仅使用内置函数的方法。
    【解决方案2】:

    在以后的 Oracle 版本中,您可以在 SELECT 语句的子查询分解 (WITH) 子句中包含函数。然后,您可以使用this answer

    WITH FUNCTION get_key(
        pos  IN PLS_INTEGER,
        json IN CLOB
      ) RETURN VARCHAR2 
      AS
        doc_keys JSON_KEY_LIST;
      BEGIN
        doc_keys := JSON_OBJECT_T.PARSE ( json ).GET_KEYS;
        RETURN doc_keys( pos );
      END get_key;
    SELECT get_key( j.pos, t.value ) AS key,
           j.value
    FROM   table_name t
           CROSS APPLY JSON_TABLE(
             t.value,
             '$.*'
             COLUMNS (
               pos   FOR ORDINALITY,
               value PATH '$'
             )
           ) j;
    

    其中,对于样本数据:

    CREATE TABLE table_name ( value VARCHAR2(4000) CHECK (value IS JSON) );
    INSERT INTO table_name (value) VALUES ('{a:100, b:200, c:300}');
    

    输出:

    KEY VALUE
    a 100
    b 200
    c 300

    仅限内置函数,例如json_table,json_dataguide

    您将与这些限制作斗争:

    • JSON_QUERY 只允许路径的文字值;您不能传递动态路径值。
    • JSON_TABLE 确实允许在 COLUMNS 子句中使用动态路径,但不会为这些动态路径返回值。

    例如:

    SELECT t.value AS json,
           SUBSTR(p.path, 3) AS key,
           JSON_QUERY(t.value, p.path) AS value
    FROM   table_name t
           CROSS JOIN LATERAL(
             SELECT JSON_DATAGUIDE(t.value) AS data
             FROM   DUAL
           ) d
           CROSS JOIN LATERAL(
             SELECT path
             FROM   JSON_TABLE(
                      d.data,
                      '$[*]'
                      COLUMNS(
                        path VARCHAR2(20) PATH '$."o:path"'
                      )
                    )
           ) p;
    

    输出:

    ORA-40454: path expression not a literal
    

    和:

    SELECT t.value AS json,
           SUBSTR(p.path, 3) AS key,
           v.val AS value
    FROM   table_name t
           CROSS JOIN LATERAL(
             SELECT JSON_DATAGUIDE(t.value) AS data
             FROM   DUAL
           ) d
           CROSS JOIN LATERAL(
             SELECT path
             FROM   JSON_TABLE(
                      d.data,
                      '$[*]'
                      COLUMNS(
                        path VARCHAR2(20) PATH '$."o:path"'
                      )
                    )
           ) p
           CROSS JOIN LATERAL(
             SELECT val
             FROM   JSON_TABLE(
                      t.value,
                      '$'
                      COLUMNS(
                        val VARCHAR2(20) PATH p.path
                      )
                    )
           ) v;
    

    输出:

    JSON KEY VALUE
    {"a":100, "b":200, "c":300} a <null>
    {"a":100, "b":200, "c":300} b <null>
    {"a":100, "b":200, "c":300} c <null>

    虽然查询有效,但它不会动态获取值。 (注意:如果您使用文字路径而不是动态路径,则该查询将起作用。)

    db小提琴here

    【讨论】:

    • 如何使用动态路径获取值来解决这个问题?动态路径是否有替代方法。对于每个值,文字路径只给我 100。每个值应该不同@MT0
    • @samurai-jack07 使用get_keys 函数(在SELECT 语句中定义,因此您不需要全局创建函数)查看我的答案的第一部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-17
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-06
    相关资源
    最近更新 更多