为什么在JSONB中将显式的'null'提取为文本会产生SQL'null'?
我试图理解PostgreSQL的为什么在JSONB中将显式的'null'提取为文本会产生SQL'null'?,json,postgresql,null,jsonb,Json,Postgresql,Null,Jsonb,我试图理解PostgreSQL的jsonb类型中的处理nulls。因为 # select 'null'::jsonb is null; ?column? ---------- f (1 row) 我假设它们不同于SQLnulls(这很有意义)- SQLNULL是一个不同的概念 因此,这两个问题一点也不奇怪: # select '{"a": 1, "b": null}'::jsonb->'b' is null; ?column? ---------- f (1 row) #
jsonb
类型中的处理null
s。因为
# select 'null'::jsonb is null;
?column?
----------
f
(1 row)
我假设它们不同于SQLnull
s(这很有意义)-
SQLNULL是一个不同的概念
因此,这两个问题一点也不奇怪:
# 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)
per:
如果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)
后一个我可以理解-我们从提取中得到一个SQLnull
,将null
强制转换为text
将其保留为null
-我假设->
是这样工作的,如所述
field/element/path提取运算符返回的类型与其左侧输入(json或jsonb)相同,但指定为返回文本的运算符除外,后者将值强制为文本
(顺便说一句,我找不到一个确认,将SQLnull
强制转换为任何其他类型会再次在PostgreSQL中产生null
——它是明确地写在某个地方的吗?)
但前者对我来说是个谜。提取应该会给我一个jsonb
null
,我认为对文本进行转换应该会给我'null'
(即一个表示“null”的字符串),就像
# select ('null'::jsonb)::text;
text
------
null
(1 row)
但它仍然返回一个正确的SQLnull
为什么会这样?在某种程度上,这是实施者的意见问题;在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)
这里,与上面的cast不同,PostgreSQL试图在SQL中找到与JSON值最接近的等价物。您不希望字符串“null”
保留其双引号,因为这在SQL中是完全不同的字符串,对吗
但另一方面,如果“null”
和null
在SQL中以相同的方式表示,它也会感觉不正确,不是吗
据我所知,JSONnull
表示“不在那里”,这是sqlnull的含义之一。另外,有一个值为null
的JSON属性意味着忽略该属性,不是吗
因此,尽管有争论的余地,但我认为它的实施方式背后有一些韵律和原因。它还会有什么回报?它不能返回JSON null,因为操作符显式地根本不返回JSON。它必须应用一些映射,如果不是这样的话,那又怎样呢?好吧,我说过-我期望字符串'null'
,比如select('null'::jsonb)::text代码>…非常感谢!这很有趣,现在对我来说很有意义<代码>
这是我的博客文章:
我找不到对你的博客发表评论的方法,所以我把它放在这里:1。有一个“客栈”而不是“in”,2。关于“将null
强制转换为任何结果都会导致null
(我在PostgreSQL手册中找不到这方面的证据,但一些实验似乎证实了这一行为,这是完全有道理的):这是SQL标准规定的:“每种数据类型都包含一个特殊的值,称为空值,有时用关键字null
表示”谢谢!注释页面的链接在左下角,所以请随意留下关于null
s的注释(我修正了输入错误)。
SELECT (JSONB '{"a": "null"}' -> 'a')::text,
(JSONB '{"a": null}' -> 'a')::text;
text | text
--------+------
"null" | null
(1 row)