PostgreSQL 用另一列的值更新 JSONB 列

Ole*_*yan 6 sql postgresql jsonb postgresql-9.4

我想将数据从一列 (varchar) 迁移到另一列 (jsonb)

   Column   |            Type             |                       Modifiers                        
------------+-----------------------------+--------------------------------------------------------
 id         | integer                     | not null default nextval('merchants_id_seq'::regclass)
 name       | character varying           | not null
 nameb      | jsonb                       | not null default '{}'::jsonb
Run Code Online (Sandbox Code Playgroud)

所以这nameb将成为{"en": "$name"}其中$name的一个值name字段。

例如:

选择名称,名称 b

前:

                 name                 |   nameb    
--------------------------------------+------------
 hello                                | {} 
 world                                | {}
Run Code Online (Sandbox Code Playgroud)

后:

                 name                 |   nameb    
--------------------------------------+------------
 hello                                | {"en": "hello"}
 world                                | {"en": "world"}
Run Code Online (Sandbox Code Playgroud)

使用常规类型我可以做到UPDATE SET whatever = (SELECT ...),但是如何使用 jsonb 做到这一点?

UPDATE merchants SET nameb = (SELECT '{"en": "fillme!"}'::jsonb);有效,但如何设置“fillme!” 来自另一个领域的价值?

Dmi*_*kin 8

这可以通过 jsonb_build_object 函数来完成,该函数允许您从简单的数据类型构建 json 对象。

所以要做你想做的事:

update merchants set nameb = nameb || jsonb_build_object('en', name)
Run Code Online (Sandbox Code Playgroud)

通过 json_build_object,我们可以根据“name”列中的值动态地生成 {"en": "hello"}, {"en": "world"} ..。之后我们可以简单地用 || 连接到 jsonb 值 操作员。

如果 nameb 为 NULL,这将不起作用,因为 NULL 会“吃掉”所有内容,结果将再次为 NULL。在这种情况下,我建议使用 COALESCE:

update merchants set nameb = COALESCE(nameb, '{}') || jsonb_build_object('en', name)
Run Code Online (Sandbox Code Playgroud)

实现相同目的的另一种方法是使用 jsonb_set 函数。对于这种特殊情况,它有点矫枉过正,但是如果您需要在 json 深处的某个地方设置一些键,它可能会很方便:

update merchants set nameb = jsonb_set(nameb, '{en}', ('"' || name || '"')::jsonb)
Run Code Online (Sandbox Code Playgroud)

这看起来很奇怪,因为我们必须构造用引号括起来的字符串,即: '"hello"' 将其设置为 'en' 键的值。如果您需要设置一些 json,jsonb_build_object 会更方便。


Ole*_*yan 3

我找到了解决方案:

UPDATE merchants AS m1 
SET nameb = (
  SELECT row_to_json(t) FROM (
    SELECT name as en FROM merchants AS m2 WHERE m1.id = m2.id
  ) t
)::jsonb;
Run Code Online (Sandbox Code Playgroud)

不确定这是否正确,但它有效