如何在嵌套的jsonb postgres列中设置时间戳键值对

问题描述 投票:0回答:1

我尝试使用下面的 postgres sql 脚本来设置列“ack”的时间戳键值对,但出现以下错误。有谁知道如何纠正它?当值只是一个简单的字符串而不是时间戳时,我不会遇到问题。

--Sql script
UPDATE TABLE_NAME set ack=jsonb_set(ack , '{clientZ}', '{"timestamp": "ABCDE"}')

--Result I am getting 
{"clientZ": {"timestamp": "ABCDE"}} -- this works fine

--Sql script 
UPDATE TABLE_NAME set ack=jsonb_set(ack , '{clientZ}', '{"timestamp": to_jsonb(to_char(now(), ''YYYY-MM-DD HH:MI:SS.MS TZHTZM''))}')

--Result I am expecting 
{"clientZ": {"timestamp": "2024-10-30 11:31:38.765 -0500"}}

--Error I am getting 
SQL Error [42601]: ERROR: syntax error at or near "to_jsonb"

sql postgresql jsonb
1个回答
0
投票

谢谢你的提问!我认为您已经非常接近解决方案了。

jsonb_set 的第三个参数必须是有效的 JSON。在你的例子中,它是

'{"timestamp": to_jsonb(to_char(now(), ''YYYY-MM-DD HH:MI:SS.MS TZHTZM''))}'
,它不是有效的 JSON(to_jsonb(... 部分缺少引号)。to_jsonb 函数不是在字符串中求值,而是逐个字母地进行计算。这可以从仅转换中看出字符串转为 JSON:

-- gives an error about bad JSON
select '{"timestamp": to_jsonb(to_char(now(), ''YYYY-MM-DD HH:MI:SS.MS TZHTZM''))}'::jsonb;

如果要替换整个 JSON 对象,则必须从其元素构造它:

select jsonb_build_object('timestamp', to_char(now(), 'YYYY-MM-DD HH:MI:SS.MS TZHTZM'));
jsonb_build_object
{"时间戳": "2024-10-30 07:01:17.003 +0100"}

jsonb_build_object 采用一个键和一个值(或多个)。

然后您可以使用结果作为替换值,如下所示:

select jsonb_set('{"clientZ":{"timestamp":"X"}}', 
                 '{clientZ}',
                 jsonb_build_object('timestamp', to_char(now(), 'YYYY-MM-DD HH:MI:SS.MS TZHTZM')));
jsonb_set
{"clientZ": {"时间戳": "2024-10-30 07:02:26.420 +0100"}}

在您的情况下,似乎没有必要替换包含时间戳的整个对象。如果您可以单独设置时间戳字段,请将时间戳移到

path
数组中:

select jsonb_set('{"clientZ":{"timestamp":"X"}}',
                 '{clientZ,timestamp}',
                 to_jsonb(to_char(now(), 'YYYY-MM-DD HH:MI:SS.MS TZHTZM')::text));

我们得到 |jsonb_set| |---------| |{"clientZ": {"timestamp": "2024-10-30 06:48:18.018 +0100"}}|

当然还有其他方法,例如通过连接所有部分来构建 JSON 对象的字符串表示形式,但正确引用所有部分会很乏味,所以这似乎是一个更简单的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.