如何检查MySQL JSON列属性为空?

vm0i2vca  于 2023-03-17  发布在  Mysql
关注(0)|答案(3)|浏览(327)

我正在使用MySQL 8.0.21。我需要编写一个使用JSON列类型的查询。JSON文档中的一些数据有空值,我想过滤掉这些空值。
可能的行示例,JSON文档中的大多数属性已被删除以简化:

jsonColumn
'{"value":96.0}'
'{"value":null}' -- This is the row I am trying to filter out
NULL

以下是我的尝试:

-- Removed columns where jsonColumn was NULL but, NOT columns where jsonColumn->'$.value' was null. 
SELECT * 
FROM <table>
WHERE jsonColumn->'$.value' IS NOT NULL;

-- Note the unquote syntax, ->>. The code above uses ->.
-- Produced the same result as the code above.
SELECT * 
FROM <table>
WHERE jsonColumn->>'$.value' IS NOT NULL;

-- Produced same result as the two above. Not surprised because -> is an alias of JSON_EXTRACT
SELECT * 
FROM <table>
WHERE JSON_EXTRACT(jsonColumn, '$.value') IS NOT NULL;

-- Produced same result as the three above. Not surprised because ->> is an alias of JSON_EXTRACT
SELECT * 
FROM <table>
WHERE JSON_UNQUOTE(JSON_EXTRACT(jsonColumn, '$.value')) IS NOT NULL;

-- Didn't really expect this to work. It didn't work. For some reason it filters out all records from the select.
SELECT *
FROM <table>
WHERE jsonColumn->'$.value' != NULL;

-- Unquote syntax again. Produced the same result as the code above.
SELECT *
FROM <table>
WHERE jsonColumn->>'$.value' != NULL;

-- Didn't expect this to work. Filters out all records from the select.
SELECT *
FROM <table>
WHERE JSON_EXTRACT(jsonColumn, '$.value') != NULL;

-- Didn't expect this to work. Filters out all records from the select.
SELECT *
FROM <table>
WHERE JSON_UNQUOTE(JSON_EXTRACT(jsonColumn, '$.value')) != NULL;

-- I also tried adding a boolean value to one of the JSON documents, '{"test":true}'. These queries did not select the record with this JSON document.
SELECT * 
FROM <table>
WHERE jsonColumn->'$.test' IS TRUE;
SELECT * 
FROM <table>
WHERE jsonColumn->>'$.test' IS TRUE;

我注意到一些有趣的事情...
比较其他值起作用。例如...

-- This query seems to work fine. It filters out all records except those where jsonColumn.value is 96.
SELECT *
FROM <table>
WHERE jsonColumn->'$.value' = 96;

我注意到的另一个有趣的事情,在上面一些例子的注解中提到过,是空值检查的一些奇怪行为,如果jsonColumn是空值,空值检查会过滤掉记录,即使我知道我正在访问jsonColumn-〉'$. value'。
不确定这是否清楚,所以让我详细说明一下...

-- WHERE jsonColumn->>'$.value' IS NOT NULL
jsonColumn
'{"value":96.0}'
'{"value":null}' -- This is the row I am trying to filter out. It does NOT get filtered out.
NULL -- This row does get filtered out.

根据this post,使用-〉〉和JSON_UNQUOTE & JSON_EXTRACT与IS NOT NULL比较应该是有效的。
老实说,这可能是IS语句和JSON列类型的一个bug。已经有一些奇怪的行为,它与JSON文档而不是JSON文档的值进行比较。
不管怎样,有没有什么方法可以做到这一点?或者我一直在尝试的方法被证实是正确的,而这只是一个bug?

a0x5cqrl

a0x5cqrl1#

根据Barmar的评论...
显然,这在8.0.13. forums.mysql.com/read.php?176,670072,670072之前的某个时间发生了更改
论坛帖子中的一个变通方案似乎使用了JSON_TYPE。看起来是一个糟糕的变通方案tbh。

SET @doc = JSON_OBJECT('a', NULL);
SELECT JSON_UNQUOTE(IF(JSON_TYPE(JSON_EXTRACT(@doc,'$.a')) = 'NULL', NULL, JSON_EXTRACT(@doc,'$.a'))) as C1,
JSON_UNQUOTE(JSON_EXTRACT(@doc,'$.b')) as C2;

论坛帖子说(关于在变通方案之前发布的代码)...
C2实际上设置为NULL,但C1作为4个字符的“null”字符串返回。
所以我开始搞字符串比较...

// This filtered out NULL jsonColumn but, NOT NULL jsonColumn->'$.value'
SELECT *
FROM <table>
WHERE jsonColumn->'$.value' != 'null';

jsonColumn
'{"value":96.0}'
'{"value":"null"}' -- Not originally apart of my dataset but, this does get filtered out. Which is very interesting...
'{"value":null}' -- This does NOT get filtered out.
NULL -- This row does get filtered out.

// This filtered out both NULL jsonColumn AND NULL jsonColumn->'$.value'
SELECT *
FROM <table>
WHERE jsonColumn->>'$.value' != 'null';

jsonColumn
'{"value":96.0}'
'{"value":"null"}' -- Not originally apart of my dataset but, this does get filtered out.
'{"value":null}' -- This does get filtered out.
NULL -- This row does get filtered out.
5n0oy7gb

5n0oy7gb2#

更简单的方法是使用LIKE作为运算符
SELECT * FROM WHERE jsonColumn-〉'$.value'类似于低位('NULL');
LOWER用于验证它是null还是NULL,因为在我的测试中它确实不同

iih3973s

iih3973s3#

使用函数JSON_VALUE(在8.0.21中引入),可以从包含JSON数据的列中正确读取null值。

SELECT * 
FROM <table>
WHERE JSON_VALUE(jsonColumn, '$.value') IS NOT NULL;

您也可以使用类似的查询在没有表的情况下验证这一点

SELECT 
 JSON_VALUE('{"foo": null}', "$.foo"),
 JSON_VALUE('{"foo": 96.0}', "$.foo");

注意文档中的此注解
如果未由RETURNING子句指定,则JSON_VALUE()函数的返回类型为VARCHAR(512)
例如,如果您要提取一个可能超过512个字符的嵌套JSON对象,则可以指定JSON_VALUE(jsonColumn, '$.value' RETURNING JSON),当然,如果您确定预期的数据,则可以指定其他类型,如UNSIGNEDDOUBLE等。

相关问题