json - 为什么将 JSONB 中的显式“null”提取为文本会产生 SQL“null”?
问题描述
我试图理解PostgreSQL类型null
中的处理 s 。jsonb
因为
# select 'null'::jsonb is null;
?column?
----------
f
(1 row)
我假设它们与 SQL 不同null
(这是有道理的)-根据手册,
SQL NULL 是一个不同的概念。
因此,这两个查询一点也不奇怪:
# select '{"a": 1, "b": null}'::jsonb->'b' is null;
?column?
----------
f
(1 row)
# select '{"a": 1, "b": null}'::jsonb->'c' is null;
?column?
----------
t
(1 row)
根据手册:
如果 JSON 输入没有正确的结构来匹配请求,则字段/元素/路径提取运算符返回 NULL,而不是失败;例如,如果不存在这样的元素。
然而,惊喜开始的地方是:
# select '{"a": 1, "b": null}'::jsonb->>'b' is null;
?column?
----------
t
(1 row)
# select '{"a": 1, "b": null}'::jsonb->>'c' is null;
?column?
----------
t
(1 row)
null
后一个我可以理解-我们从提取中得到一个SQL ,然后将其转换null
为text
保留它null
-我认为按照手册所述->>
方式工作
字段/元素/路径提取运算符返回与其左侧输入相同的类型(json 或 jsonb),但指定为返回文本的那些除外,它将值强制为文本。
(顺便说一句,我无法确认将 SQLnull
转换为任何其他类型null
在 PostgreSQL 中再次产生 - 它是否明确写在某处?)
但前者对我来说是个谜。提取应该给我一个jsonb
null
,我认为强制转换text
应该给我'null'
(即,一个字符串说“null”),就像
# select ('null'::jsonb)::text;
text
------
null
(1 row)
但它返回一个正确的 SQL null
。
为什么呢?
解决方案
在某种程度上,这是实施者的意见问题;在 JSON 数据类型和 SQL 数据类型之间进行转换时,并不总是可以找到完美的对应关系,尤其是 SQL NULL 非常奇怪。
但是它的实现方式有一定的逻辑。
SELECT (JSONB '{"a": "null"}' -> 'a')::text,
(JSONB '{"a": null}' -> 'a')::text;
text | text
--------+------
"null" | null
(1 row)
转换为text
始终会产生一个结果,当转换回原始类型时,会产生原始值。这是 PostgreSQL 的设计原则。
所以 JSON 字符串"null"
和 JSONnull
将被转换为不同的字符串。
现在看看这个:
SELECT JSONB '{"a": "null"}' ->> 'a',
JSONB '{"a": null}' ->> 'a';
?column? | ?column?
----------+----------
null |
(1 row)
在这里,与上面的转换不同,PostgreSQL 尝试在 SQL 中找到最接近的 JSON 值等价物。您不希望字符串"null"
保留其双引号,因为这在 SQL 中将是完全不同的字符串,对吧?
但另一方面,如果"null"
并且null
在 SQL 中以相同的方式表示,它也会感觉不对,不是吗?
据我所知,JSONnull
的意思是“不存在”,这也是 SQL NULL 的含义之一。此外,拥有一个值为 的 JSON 属性null
意味着与省略该属性大致相同,不是吗?
因此,尽管有争论的余地,但我认为它的实施方式背后有一些押韵和原因。
推荐阅读
- angular - Angular Pipe:将字符串转换为Json并获取成员值
- c# - 有没有办法声明一个类似于 Linq 的 CustomWhere() 方法并在没有多余项的情况下调用它?
- mongodb - setLogLevel 和 setProfilingLevel MongoDB 之间的区别
- android - 在从 ViewModel/LiveData 首次更新之前,Android 中的格式化字符串无法正确显示
- sql - Where、Having 和 OR 子句
- python - 递归神经网络
- sql - 提高 SQL 查询的性能
- sql - SQL查询所有注册但仅选择一列之一
- php - 当我在 Laravel 上创建新行时出现非法偏移类型
- javascript - 本地捕获的“抛出”异常 - 代码重复或警告