PostgreSQL:如何使用同一个表的另一列中的值更新JSON(jsonb数据类型)?

rks48beu  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(2)|浏览(157)

我在Postgres(版本12.12)中定义了以下表格:

Table "public.test"
  Column   | Type  | Collation | Nullable | Default
-----------+-------+-----------+----------+---------
 uuid      | uuid  |           |          |
 name      | text  |           |          |
 json_data | jsonb |           |          |

字符串
下面是一个示例行:

uuid                 | name |  json
 12345678-3ffd-472b-ac39-31eacc4a6785 | foo  | {"id": 1132}


我想使用同一个表中不同列的值更新json_data。类似这样:

UPDATE test SET json_data = json_data || '{"xyz":{"enabled": false, "uuid": test.uuid}}';


其中uuid的值是来自同一行的“uuid”值。因此,我希望所需的更新行看起来像这样:

uuid                 | name |  json
 12345678-3ffd-472b-ac39-31eacc4a6785 | foo  | {"id": 1132, "xyz":{"enabled": false, "uuid": "12345678-3ffd-472b-ac39-31eacc4a6785"}}


尝试了这个,但得到了一个语法错误:

UPDATE test SET json_data = json_data || '{"xyz":{"enabled": false, "uuid": test.uuid}}';

ERROR:  invalid input syntax for type json
LINE 1: update test set json_data = json_data || '{"xyz":{"e...
                                                 ^
DETAIL:  Token "test" is invalid.
CONTEXT:  JSON data, line 1: {"xyz":{"enabled": false, "uuid": test...

j2cgzkjk

j2cgzkjk1#

你不能把一个像test.uuid这样的SQL表达式放在一个文本中,然后期望它被计算,你可以使用字符串插值和类型转换,但是那很难看,很容易搞砸。
相反,使用jsonb_build_object函数构建json(b)值:

UPDATE test
SET json_data = json_data || jsonb_build_object(
  'xyz', jsonb_build_object(
    'enabled', FALSE,
    'uuid', test.uuid
  )
);

字符串
或者,您可以使用jsonb_set而不是串联:

UPDATE test
SET json_data = jsonb_set(
  jsonb_set(
    json_data,
    '{xyz,enabled}',
    FALSE,
  ),
  '{xyz,uuid}',
  test.uuid
);


但是这是相当丑陋的,我只建议在设置单个属性时使用它。

y53ybaqx

y53ybaqx2#

因为你使用的是json而不是jsonb,所以你需要一点强制转换来使用json-functions来更新json内容:

UPDATE test
SET json_data = jsonb_set(COALESCE(json_data,'{}')::jsonb
        , '{xyz}' -- target key
        , jsonb_build_object( -- new content for the targeted key
                'enabled'   , FALSE
                , 'uuid'    , uuid -- from your column "uuid"
            )
      , TRUE -- create key if it doesn't exist yet
      );

字符串
现在你不需要任何文本函数,当你在某个列中有一些NULL时,你是安全的。
NULL||“一些内容”
结果为NULL

相关问题