此代码:
SELECT JSON_EXTRACT('{"hello": null}', '$.hello')
退货
null
.
不过,这不是MySQL原生的
NULL
。例如,这个:
SELECT COALESCE(JSON_EXTRACT('{"hello": null}', '$.hello'), 'world')
也产生
null
.
如何将此 JSON
null
转换为 MySQL 原生 NULL
?
我想我可以使用
IF
进行一些比较,但这似乎不是正确的方法...
不幸的是
CAST('{}' AS JSON)
在这种情况下不起作用,
但是NULLIF
有效:
完整方法:
SELECT NULLIF(JSON_UNQUOTE(JSON_EXTRACT('{"hello": null}', '$.hello')), 'null') IS NULL;
短路:
SELECT NULLIF(helloColumn ->> '$.hello', 'null') IS NULL IS NULL;
这个问题是关于MySQL 5.7的,但是我想补充一下MySQL 8.0的解决方案。
JSON_VALUE
函数(SQL Standard 的一部分)来提取值,并可选择将值转换为(MySQL)类型。
mysql> SET @doc = '{"a": null}';
mysql> SELECT JSON_VALUE(@doc, '$.a' RETURNING SIGNED);
+------------------------------------------+
| JSON_VALUE(@doc, '$.a' RETURNING SIGNED) |
+------------------------------------------+
| NULL |
+------------------------------------------+
mysql> SET @doc = '{"a": 2}';
mysql> SELECT JSON_VALUE(@doc, '$.a' RETURNING SIGNED);
+------------------------------------------+
| JSON_VALUE(@doc, '$.a' RETURNING SIGNED) |
+------------------------------------------+
| 2 |
+------------------------------------------+
假设您有一个名为“mytable”的表,其中包含一个名为“data”的 json 列。我通常必须使用这样的结构:
SELECT
CASE WHEN data->>'$.myfield' = 'null' THEN NULL ELSE data->>'$.myfield' END myfield
FROM mytable
或者创建一个虚拟字段如下:
ALTER TABLE mytable ADD myfield VARCHAR(200) GENERATED ALWAYS AS (
CASE WHEN data->>'$.myfield' = 'null' THEN NULL ELSE data->>'$.myfield' END
) VIRTUAL;
看起来官方讨论在进行中但不太活跃
这里还有一个陪审团操纵:
mysql> SELECT CAST('null' AS JSON), JSON_TYPE(CAST('null' AS JSON)) = 'NULL';
+----------------------+------------------------------------------+
| CAST('null' AS JSON) | JSON_TYPE(CAST('null' AS JSON)) = 'NULL' |
+----------------------+------------------------------------------+
| null | 1 |
+----------------------+------------------------------------------+
1 row in set (0.00 sec)
mysql> select @@version;
+---------------+
| @@version |
+---------------+
| 5.7.21-20-log |
+---------------+
1 row in set (0.00 sec)
假设您有一个表,其中包含
j
类型的列 JSON
并且对于该列,您有一个可以为 null 的嵌套属性。例子:
{"hello": "world"}
{"hello": null}
...
在 MySQL 5.7.13+ 中,选择
hello
值的最简单方法是使用如下内容:
SELECT j->>'$.hello' FROM ...
但是,该查询的结果将具有
null
string (LONGTEXT
) 值而不是特殊的 SQL NULL
值:
world -- that's a string
null -- that's also a string
...
验证的一种方法是运行类似的东西:
SELECT COALESCE(j->>'$.hello', 'YouWillNeverSeeMe:(((')
->
而不是 ->>
,我们会得到:
"world" -- that's a string (note the quotation marks)
null -- that's also a string (with no quotation marks)
...
那么我们如何获取 JSON
null
值作为 SQL NULL
值?
在 MySQL 8.0.21+ 中,我们可以使用 JSON_VALUE 函数并执行如下操作:
SELECT JSON_VALUE(j->'$.hello', '$') FROM ...
结果会是:
world -- that's a string
[NULL] -- that's NOT a string but the special SQL NULL value
...
请注意,如果我们在这里使用
->>
而不是 ->
,我们将获取:
[NULL] -- that's NOT a string but the special SQL NULL value
[NULL] -- that's NOT a string but the special SQL NULL value
...
我不知道理想的解决方案。 sergolius 提供的 answer 看起来简单而漂亮,但它有一个应该考虑的潜在缺陷。假设 Alice 和 Bob 生了一个孩子,他们决定将其命名为 Null(嘿,我不是来评判的!)。假设 Null 最终出现在我们数据库的 JSON 列中。所以不是获取:
Alice
[NULL]
Bob
Null
John
...
,我们可能会得到:
Alice
[NULL]
Bob
[NULL] -- Oops! Where did Null go?
John
...
SELECT COALESCE(IF(JSON_TYPE(JSON_EXTRACT('{"hello":null}', '$.hello')) = 'NULL', NULL, JSON_EXTRACT('{"hello":null}', '$.hello')), 'world');
您可以通过运行创建自定义函数
TO_NULL
:
-- To check if JSON value is null, if so return SQL null, and if not return original JSON value.
-- There are two nulls, SQL null and JSON null, they are not equal.
-- More information: https://stackoverflow.com/questions/37795654
DROP FUNCTION IF EXISTS TO_NULL;
CREATE FUNCTION TO_NULL(a JSON) RETURNS JSON
BEGIN
RETURN IF(JSON_TYPE(a) = 'NULL', NULL, a);
END;
比这样使用它:
SELECT TO_NULL(JSON_EXTRACT('null', '$')) IS NULL;
以下方法适用于 mysql 8
中的
undefined
和
null
值
SELECT data,
CAST(data->>'$.a' AS JSON) <=> CAST('null' AS JSON) 'null',
data->>'$.b' IS NULL 'NULL' FROM t;
数据 | 空 | 空 |
---|---|---|
{“a”:空} | 1 | 1 |
所以要检查字段是否没有值,你可以在你的查询中使用这样的东西
SELECT CAST(data->>'$.a' AS JSON) <=> CAST('null' AS JSON) OR data->>'$.a' IS NULL FROM t;