如何修改PostgreSQL JSONB数据类型中的单个属性值?
如何修改PostgreSQL JSONB数据类型中的单个字段 假设我有一张叫做动物的桌子,像这样:如何修改PostgreSQL JSONB数据类型中的单个属性值?,json,postgresql,jsonb,Json,Postgresql,Jsonb,如何修改PostgreSQL JSONB数据类型中的单个字段 假设我有一张叫做动物的桌子,像这样: id info ------------------------------------------------------------ 49493 {"habit1":"fly","habit2":"dive","location":"SONOMA NARITE"} 我只想简单地更改location属性的值(比如,文本大小写)。因此,更新后的结果是 id i
id info
------------------------------------------------------------
49493 {"habit1":"fly","habit2":"dive","location":"SONOMA NARITE"}
我只想简单地更改location属性的值(比如,文本大小写)。因此,更新后的结果是
id info
------------------------------------------------------------
49493 {"habit1":"fly","habit2":"dive","location":"sonoma narite"}
我在下面试过了,但不起作用
update animal set info=jsonb_set(info, '{location}', LOWER(info->>'location'), true) where id='49493';
----------------------------------
ERROR: function jsonb_set(jsonb, unknown, text, boolean) does not exist
LINE 7: update animal set info=jsonb_set(info, '{con...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
********** Error **********
ERROR: function jsonb_set(jsonb, unknown, text, boolean) does not exist
如果我只知道更新后的值是什么,那么我可以使用:
update animal set info=jsonb_set(info, '{location}', '"sonoma narite"', true) where id='49493';
但是,如果文本值未知,我们只想做一些简单的操作,比如追加、前置、大写/小写,我就无法简单地找到答案
我感到惊讶的是,jsonb集合函数并没有提供这样一个简单的操作,即只尝试更新jsonb中文本属性的大小写
有人能帮忙吗?jsonb_set()的第三个参数应该是
jsonb
类型。问题在于将文本字符串转换为jsonb字符串时,需要使用双引号中的字符串。您可以使用concat()
或format()
:
在Postgres 9.4中,您应该使用jsonb_each_text()取消json列的测试,聚合键和值,动态修改适当的值,最后构建json对象:
update animal a
set info = u.info
from (
select id, json_object(
array_agg(key),
array_agg(
case key when 'location' then lower(value)
else value end))::jsonb as info
from animal,
lateral jsonb_each_text(info)
group by 1
) u
where u.id = a.id
and a.id = 49493;
如果您可以创建函数,此解决方案可能会更令人愉快:
create or replace function update_info(info jsonb)
returns jsonb language sql as $$
select json_object(
array_agg(key),
array_agg(
case key when 'location' then lower(value)
else value end))::jsonb
from jsonb_each_text(info)
$$
update animal
set info = update_info(info)
where id = 49493;
我想在这里分享一些好消息。多亏了克林,他的投入帮助我发现了这个解决方案。在上面的例子中。如果我只是使用concat函数,那么我在klin发布的代码中发现的问题就得到了解决(简而言之,它只在文本值包含空格时才起作用)。现在我可以降低单个属性值的大小写
UPDATE test1 set info=jsonb_set(info, '{location}', concat('"',lower(info->>'locatioin'),'"')::jsonb, true) returning *;
谢谢克林,我会试试看,然后告诉你。我的查询中没有标记“someooopath”。我无法调试一个我看不到的查询…嗨,克林,我想我发现了一个问题,它不起作用。假设上面示例中的“location”属性中有下划线。postgres将抛出类似“类型json的输入语法无效”的错误。或者如果此属性的值中没有空格。它也会抛出错误信息列下的这个值不起作用{“位置”:“实体模型属性”}#信息列下的这个值也不起作用{“位置”:“实体模型属性”}#信息列下的这个值将起作用{“位置”:“实体模型属性”}是的,你是对的。在这些情况下,
quote_ident()
不是一个好的选择。改用concat()
或format()
。请看修改后的答案。嗨,克林,我遇到了另一个问题。我的开发机器有Postgres v9.6,它有jsonb_集功能,但我们的生产服务器使用的是Postgres v9.4.5,它没有jsonb_集功能。所以我不能用这个脚本。如果你不介意的话,你能帮我一下还是给我一些建议?谢谢我尝试更新test_table set info=jsonb_set(info,{location},''cityTest',true),其中id='123';但由于函数不存在,它仍然给出错误。我正在使用postgresql 9.4.8
UPDATE test1 set info=jsonb_set(info, '{location}', concat('"',lower(info->>'locatioin'),'"')::jsonb, true) returning *;