为什么ORACLE中的JSON函数在与搜索索引和NULL值一起使用时不获取数据?

1l5u6lss  于 2023-06-05  发布在  Oracle
关注(0)|答案(1)|浏览(229)

我面临的问题是关于null在ORACLE中的JSON_VALUE()函数的使用。我有一个表,在名为“JSON_COLUMN”的BLOB类型列中,有一个json值,它要么是{"foo":"111"},要么是{"notfoo":"111"},要么是{"foo":null}
基本上,我无法使用oracle函数JSON_VALUE()获取“JSON_COLUMN”列中包含字段foo IS NULL或字段"foo"="111"的数据的行。
我尝试了以下查询:

SELECT * FROM MY_TABLE
WHERE JSON_VALUE(JSON_COLUMN, "$.foo") IS NULL
   OR JSON_VALUE(JSON_COLUMN, "$.foo") = "111"

但这不会获取JSON看起来像{"notfoo":"111"}{"foo":null}的行。
我还尝试了手术室的每一个独立的侧面,每一个都很好。我也试过这个查询

SELECT * FROM MY_TABLE
WHERE JSON_VALUE(JSON_COLUMN, "$.foo") IS NULL
   OR JSON_VALUE(JSON_COLUMN, "$.foo") IS NOT NULL

我得到了预期的结果,也就是表中的所有行。
有人知道为什么JSON_VALUE函数在OR中会这样做吗?

编辑:

经过进一步调查,该问题与“OR”无关,也与我们遗漏on error部件的事实无关。我已经能够用一个最小的数据库准确地重现我的问题,我错过了一个点,在我的数据库中,我添加了一个搜索索引。
下面是一个例子,我得到的所有结果都是预期的,在添加了搜索索引之后,结果不再是我们所期望的:

CREATE TABLE DUMMY (COLUMN1 BLOB);

ALTER TABLE
    DUMMY
ADD
    CONSTRAINT DUMMY_CHECK_JSON CHECK (COLUMN1 IS JSON);

INSERT INTO
    DUMMY (column1)
VALUES
    ('{"notfoo":"222"}');

INSERT INTO
    DUMMY (column1)
VALUES
    ('{"foo":"111"}');

INSERT INTO
    DUMMY (column1)
VALUES
    ('{"foo":null}');

select
    COLUMN1
from
    DUMMY
where
    JSON_VALUE(COLUMN1, '$.foo') IS NULL
    OR JSON_VALUE(COLUMN1, '$.foo') = '111';

-- ====> 3 results

CREATE SEARCH INDEX IX_CNT_DUMMY ON DUMMY(column1) FOR JSON PARAMETERS(
    '
        DATAGUIDE OFF
        SEARCH_ON TEXT
        SYNC (EVERY "freq=secondly; interval=1")
        OPTIMIZE (EVERY "freq=weekly; byday=SAT")
    '
);

select
    COLUMN1
from
    DUMMY
where
    JSON_VALUE(COLUMN1, '$.foo') IS NULL
    OR JSON_VALUE(COLUMN1, '$.foo') = '111';

-- ====> only 1 result !

select
    COLUMN1
from
    DUMMY
where
    NOT JSON_EXISTS(COLUMN1, '$.foo')
    OR JSON_VALUE(COLUMN1, '$.foo') = '111';

-- SAME, only one result

drop index IX_CNT_DUMMY;

select
    COLUMN1
from
    DUMMY
where
    JSON_VALUE(COLUMN1, '$.foo') IS NULL
    OR JSON_VALUE(COLUMN1, '$.foo') = '111';
2cmtqfgy

2cmtqfgy1#

开始,在Oracle中,使用单引号来分隔JSON_VALUE或字符串常量中的路径。第二,这与OR无关。第三,根据您的需要,您可以指定JSON_xxx函数在您正在查找的键不存在时该怎么做(下面的“null on error”或“error on error”)

SQL> SELECT * FROM (select '{"foo":null}' json_column from dual)
  2  WHERE JSON_VALUE(JSON_COLUMN, '$.foo' error on error) IS NULL
  3*    OR JSON_VALUE(JSON_COLUMN, '$.foo'  error on error) = '111';

    JSON_COLUMN
_______________
{"foo":null}

SQL> SELECT * FROM (select '{"foo":"111"}' json_column from dual)
  2  WHERE JSON_VALUE(JSON_COLUMN, '$.foo' error on error) IS NULL
  3*    OR JSON_VALUE(JSON_COLUMN, '$.foo'  error on error) = '111';
SQL> /

     JSON_COLUMN
________________
{"foo":"111"}

SQL> SELECT * FROM (select '{"notfoo":"111"}' json_column from dual)
  2  WHERE JSON_VALUE(JSON_COLUMN, '$.foo' error on error) IS NULL
  3*    OR JSON_VALUE(JSON_COLUMN, '$.foo'  error on error) = '111';
SQL> /

Error starting at line : 1 in command -
SELECT * FROM (select '{"notfoo":"111"}' json_column from dual)
WHERE JSON_VALUE(JSON_COLUMN, '$.foo' error on error) IS NULL
   OR JSON_VALUE(JSON_COLUMN, '$.foo'  error on error) = '111'
Error report -
ORA-40462: JSON path '$.foo' evaluated to no value.

SQL>  SELECT * FROM (select '{"notfoo":"111"}' json_column from dual)
  2  WHERE JSON_VALUE(JSON_COLUMN, '$.foo' null on error) IS NULL
  3*    OR JSON_VALUE(JSON_COLUMN, '$.foo'  ) = '111';
SQL> /

        JSON_COLUMN
___________________
{"notfoo":"111"}

SQL> SELECT * FROM (select '{"notfoo":null}' json_column from dual)
  2  WHERE JSON_VALUE(JSON_COLUMN, '$.foo' null on error) IS NULL
  3*    OR JSON_VALUE(JSON_COLUMN, '$.foo'  ) = '111';
SQL> /

       JSON_COLUMN
__________________
{"notfoo":null}

SQL> SELECT * FROM (select '{"notfoo":null}' json_column from dual)
  2  WHERE JSON_VALUE(JSON_COLUMN, '$.foo' ) IS NULL
  3*    OR JSON_VALUE(JSON_COLUMN, '$.foo'  ) = '111';
SQL> /

       JSON_COLUMN
__________________
{"notfoo":null}

相关问题