此变通方法无效
CREATE FUNCTION json_array_castext(json) RETURNS text[] AS $f$
SELECT array_agg(x::text) FROM json_array_elements($1) t(x);
$f$ LANGUAGE sql IMMUTABLE;
-- Problem:
SELECT 'hello'='hello'; -- true...
SELECT (json_array_castext('["hello","world"]'))[1] = 'hello'; -- false!
那么,如何获取真实的的文本数组呢?
PS:对于所谓的“一等公民”JSONb,同样的问题。
编辑:@OtoShavadze回答得很好(评论解决了!),一个 * 清单PostgreSQL开发人员 *:为什么x::text
不是强制类型转换?(使用9.5.6页)以及为什么它不生成警告或错误?
6条答案
按热度按时间wfauudbj1#
尝试使用json_array_elements_text代替
json_array_elements
,并且不需要显式转换为文本(x::text
),因此可以用途:对于您的其他问题
为什么x::text不是强制类型转换?
这是强制类型转换,因此它不会给出任何错误,但是当将json字符串转换为如下文本时:
::text
,postgres将引号添加到值中。出于测试目的,让我们再次将函数更改为原始函数(如问题中所示),然后尝试:
如您所见,
(json_array_castext('["hello","world"]'))[1]
给出"hello"
而不是hello
,这就是为什么在比较这些值时得到false
。ocebsuys2#
测试用例:
select json_to_array('["abc"]')
=〉单元素数组select json_to_array('[]')
=〉空数组select json_to_array(null)
=〉空s5a0g9ez3#
对于PostgreSQL的这种丑陋行为,有一个丑陋的强制转换解决方案,操作符
#>>'{}'
:(编辑)2020年,第12页性能检查
我们期望专用函数
json_array_elements_text()
比用户定义的强制转换好...但是,好多少?2倍?20倍...还是只有百分之几?有时我们不能使用它,所以,有一些性能损失?
准备测试:
函数名称:
array_agg(x#>>'{}') FROM json_array_elements($1)
array_agg(x#>>'{}') FROM jsonb_array_elements($1)
array_agg(x) FROM json_array_elements_text($1)
array_agg(x) FROM jsonb_array_elements_text($1)
**结果:**所有结果几乎相同,报告的差异仅在数十亿(~3610000)次函数调用后才可察觉。对于数千次调用,它们性能相同(!)。
对于JSON和JSONb,性能差异大约为20%,因此通常(例如报告或微服务输出)可以忽略不计。
正如预期的那样,JSON转换为文本比JSONB转换快,因为JSON内部是文本,而JSONB不是。
PS:在Ubuntu 20 LTS上使用PostgreSQL 12.4,虚拟机。
voase2hg4#
Oto的answer是一个救星,但它确实有一个边界情况让我绞尽脑汁。由于强制类型转换的损耗特性,它可以完美地工作,除非您有一个空的
json
数组。在这种情况下,您可能希望返回一个空数组,但实际上它什么也不返回。作为一种解决方法,如果你只是将返回值与一个空数组连接起来,那么在实际返回的情况下不会有任何影响,但是当你得到一个空数组时,就应该做正确的事情。下面是实现该解决方案的更新后的SQL函数(适用于json
和jsonb
)。有一些像这样的特性指出了将文档数据库集成到成熟的关系数据库中的困难,但是Postgres在处理大多数这些特性方面做得非常出色。
nszi6y055#
在我的例子中,它帮助了结果反映3种状态,空,空文本数组和非空文本数组取决于输入。
whitzsjs6#
Postgres 9.6或更高版本的最佳转换函数如下:
ARRAY构造函数比
array_agg()
便宜。请参见:将其标记为
PARALLEL SAFE
也很重要。请参见dba.SE上前面的答案中的分步说明: