单个 postgresql 查询中的文本和 jsonb 连接

Posted

技术标签:

【中文标题】单个 postgresql 查询中的文本和 jsonb 连接【英文标题】:Text and jsonb concatenation in a single postgresql query 【发布时间】:2020-08-09 23:14:33 【问题描述】:

如何在 postgresql 中连接一个连接的 jsonb 对象内的字符串?换句话说,我在同一个查询中使用 JSONb 连接运算符以及文本连接运算符并遇到了麻烦。

或者...如果我应该执行一个完全不同的查询,我会很高兴听到建议。目标是更新包含 jsonb 列的行。我们不想覆盖查询中未提供的 jsonb 列中的现有键值对,并且我们还想一次更新多行。

我的查询:

update contacts as c set data = data || '"geomatch": "MATCH","latitude":'||v.latitude||''
from (values (16247746,40.814140),
      (16247747,20.900840),
      (16247748,20.890570)) as v(contact_id,latitude) where c.contact_id = v.contact_id

错误:

 ERROR:  invalid input syntax for type json
    LINE 85: update contacts as c set data = data || '"geomatch": "MATCH...
                                                     ^
    DETAIL:  The input string ended unexpectedly.
    CONTEXT:  JSON data, line 1: "geomatch": "MATCH","latitude":
    SQL state: 22P02
    Character: 4573

【问题讨论】:

我认为我需要做的就是在文本周围添加括号...数据 || ('"geomatch": "MATCH","latitude":'||v.latitude||'')::jsonb 这似乎可行。 【参考方案1】:

您可能正在寻找

SET data = data || ('"geomatch": "MATCH","latitude":'||v.latitude||'')::jsonb
--              ^^ jsonb                              ^^ text     ^^ text

但这不是构建 JSON 对象的方式——v.latitude 可能不是有效的 JSON 文字,甚至包含一些注入,例如 "", "otherKey": "oops"。 (诚​​然,在您的示例中,您控制值,它们是数字,因此可能没问题,但这仍然是一种不好的做法)。相反,请使用jsonb_build_object:

SET data = data || jsonb_build_object('geomatch', 'MATCH', 'latitude', v.latitude)

【讨论】:

好的,谢谢。这个例子在 jsonb_build_object 的推荐方法中看起来如何?也许像这样?更新联系人为 c 设置数据 = 数据 || jsonb_build_object('geomatch','MATCH','latitude',v.latitude) from (values(16247746,40.814140), (16247747,20.900840), (16247748,20.890570)) as v(contact_id,latitude) where c.contact_id = v.contact_id @GNG 是的,就像那样:-)【参考方案2】:

有两个问题。第一个是运算符优先级,防止您将jsonb 对象连接到读取的text 对象。第二个是text 块的连接需要转换为jsonb

这应该可行:

update contacts as c 
   set data = data || ('"geomatch": "MATCH","latitude":'||v.latitude||'')::jsonb
  from (values (16247746,40.814140),
               (16247747,20.900840),
               (16247748,20.890570)) as v(contact_id,latitude) 
 where c.contact_id = v.contact_id
;

【讨论】:

以上是关于单个 postgresql 查询中的文本和 jsonb 连接的主要内容,如果未能解决你的问题,请参考以下文章

用于获取存储在单个表中的 n 级父子关系的 Postgresql 查询

PostgreSQL - 如何在单个查询中获取列的最小值和最大值以及与它们关联的行?

如何在 Ruby 中使用 Where 子句 (PostgreSQL) 中的变量编写查询

在 postgresql 的单个查询中使用 WITH + DELETE 子句

无法使用 knex.js 中的连接复制 PostgresQL 查询

PostgreSQL 中具有特定模式的 Linq 和实体迁移