0

我正在研究触发器。

declare
  v_time number(11, 0);
begin
for i in 0..1
loop
  select JSON_VALUE(body, '$.sections[0].capsules[0].timer.seconds') into v_time from bodycontent where contentid=1081438;
dbms_output.put_line(v_time);
end loop;
end;

但是,索引引用不会变成动态的。

like JSON_VALUE(body, '$.sections[i].capsules[i].timer.seconds')

有什么办法可以做到这一点吗?

4

4 回答 4

0

所以,问题是你想遍历一个索引(对角地穿过数组数组,只拾取两个元素) - 但是 JSON_* 函数不能将变量用作数组索引 - 它们需要硬编码索引。

PL/SQL 对此有一个答案 -本机动态 SQL,如下所示。

但是,请注意,这种方法会重复调用JSON_VALUE()同一文档。根据实际要求(我假设您的问题中的一个仅用于说明)和文档的大小,对 进行一次调用可能会更有效JSON_TABLE(),如 MT0 的回答中所示。如果实际上您确实只是从一个非常大的文档中提取两个标量值,那么两次调用JSON_VALUE()可能是合理的,尤其是当文档比此处显示的大得多时;但是,如果您要从不太复杂的文档中提取许多标量值,那么单个调用JSON_TABLE()可能会更好,即使最终您没有使用它产生的所有数据。

无论如何 - 作为本机动态 SQL 的说明,这是替代解决方案(使用 MT0 的表):

declare
  v_time number(11, 0);
begin
  for i in 0..1 loop
    execute immediate q'#
    select json_value(body, '$.sections[#' || i ||
                      q'#].capsules[#' || i || q'#].timer.seconds')
    from   bodycontent
    where  contentid = 1081438#'
    into v_time;
    dbms_output.put_line(v_time);
  end loop;
end;
/


0
4

PL/SQL procedure successfully completed.
于 2021-02-21T06:41:54.833 回答
0

您需要连接 json 路径中的变量:

JSON_VALUE(body, '$.sections[' || to_char(i) || '].capsules[0].timer.seconds')

我真的不明白你的问题与触发器有什么关系。

于 2020-10-29T23:51:14.567 回答
0

你可以看到下面的例子:

只需在您的控制台中点击此查询并尝试了解实现。

SELECT JSON_VALUE('{
  "increment_id": "2500000043",
  "item_id": "845768",
  "options": [
    {
      "firstname": "Kevin"
    },
    {
      "firstname": "Okay"
    },
    {
      "lastname": "Test"
    }
  ]
}', '$.options[0].firstname') AS value
  FROM DUAL;
于 2021-12-28T11:15:26.410 回答
0

您可以使用JSON_TABLE

declare
  v_time number(11, 0);
begin
  for i in 0..1 loop
    SELECT time
    INTO   v_time
    FROM   bodycontent b
           CROSS APPLY
           JSON_TABLE(
             b.body,
             '$.sections[*]'
             COLUMNS (
               section_index FOR ORDINALITY,
               NESTED PATH '$.capsules[*]'
               COLUMNS (
                 capsule_index FOR ORDINALITY,
                 time NUMBER(11,0) PATH '$.timer.seconds'
               )
             )
           ) j
    WHERE  j.section_index = i + 1
    AND    j.capsule_index = i + 1
    AND    b.contentid=1081438;

    dbms_output.put_line(v_time);
  end loop;
end;
/

其中,对于测试数据:

CREATE TABLE bodycontent ( body CLOB CHECK ( body IS JSON ), contentid NUMBER );

INSERT INTO bodycontent ( body, contentid ) VALUES (
  '{"sections":[
     {"capsules":[{"timer":{"seconds":0}},{"timer":{"seconds":1}},{"timer":{"seconds":2}}]},
     {"capsules":[{"timer":{"seconds":3}},{"timer":{"seconds":4}},{"timer":{"seconds":5}}]},
     {"capsules":[{"timer":{"seconds":6}},{"timer":{"seconds":7}},{"timer":{"seconds":8}}]}]}',
  1081438
);

输出:

0
4

或者,您可以只使用查询:

SELECT section_index, capsule_index, time
FROM   bodycontent b
       CROSS APPLY
       JSON_TABLE(
         b.body,
         '$.sections[*]'
         COLUMNS (
           section_index FOR ORDINALITY,
           NESTED PATH '$.capsules[*]'
             COLUMNS (
               capsule_index FOR ORDINALITY,
               time NUMBER(11,0) PATH '$.timer.seconds'
             )
           )
       ) j
WHERE  ( j.section_index, j.capsule_index) IN ( (1,1), (2,2) )
AND    b.contentid=1081438;

哪个输出:

SECTION_INDEX | CAPSULE_INDEX | 时间
------------: | ------------: | ---:
            1 | 1 | 0
            2 | 2 | 4

(注意:来自的索引FOR ORDINALITY比 JSON 路径中的数组索引高 1。)

db<>在这里摆弄

于 2020-10-30T00:40:13.233 回答