使用postgresql 9.3我可以选择JSON数据类型的特定字段,但如何使用UPDATE修改它们?我在postgresql文档或网上任何地方都找不到这样的例子。我尝试了一些显而易见的方法:

postgres=# create table test (data json);
CREATE TABLE
postgres=# insert into test (data) values ('{"a":1,"b":2}');
INSERT 0 1
postgres=# select data->'a' from test where data->>'b' = '2';
 ?column?
----------
 1
(1 row)
postgres=# update test set data->'a' = to_json(5) where data->>'b' = '2';
ERROR:  syntax error at or near "->"
LINE 1: update test set data->'a' = to_json(5) where data->>'b' = '2...

当前回答

你也可以像这样在jsonb中原子地增加键:

UPDATE users SET counters = counters || CONCAT('{"bar":', COALESCE(counters->>'bar','0')::int + 1, '}')::jsonb WHERE id = 1;

SELECT * FROM users;

 id |    counters
----+------------
  1 | {"bar": 1}

>假设起始值为0。

更详细的解释,请看我的回答:https://stackoverflow.com/a/39076637

其他回答

在9.5中使用jsonb_set-

UPDATE objects
SET body = jsonb_set(body, '{name}', '"Mary"', true)
WHERE id = 1; 

其中body是jsonb列类型。

我发现以前的答案更适合有经验的PostgreSQL用户。这是给初学者的:

假设你有一个JSONB类型的表列,值如下:

{
    "key0": {
        "key01": "2018-05-06T12:36:11.916761+00:00",
        "key02": "DEFAULT_WEB_CONFIGURATION",
        
    "key1": {
        "key11": "Data System",
        "key12": "<p>Health,<p>my address<p>USA",
        "key13": "*Please refer to main screen labeling"
    }
}

让我们假设我们想在行中设置一个新值:

"key13": "*Please refer to main screen labeling"

取而代之的是放置值:

"key13": "See main screen labeling"

我们使用json_set()函数将一个新值赋给key13

jsonb_set()的参数

jsonb_set(target jsonb, path text[], new_value jsonb[, create_missing boolean])

在“target”-我将放置jsonb column-name(这是正在修改的表列)

"path"-是指向(包括)我们要覆盖的键的"json keys路径"

"new_value" -这是我们分配的新值

在我们的例子中,我们想要更新位于key1下的key13的值(key1 -> key13):

因此路径语法是:'{key1,key13}' (路径是最棘手的部分-因为教程是可怕的)

jsonb_set(jsonb_column,'{key1,key13}','"See main screen labeling"')

你觉得这个解决办法怎么样?

它将添加新值或更新现有值。

编辑:编辑后使其与null和空对象一起工作

Edit2:编辑使它与对象中的对象一起工作…

create or replace function updateJsonb(object1 json, object2 json)
returns jsonb
language plpgsql
as
$$
declare
    result jsonb;
    tempObj1 text;
    tempObj2 text;

begin
    tempObj1 = substr(object1::text, 2, length(object1::text) - 2); --remove the first { and last }
    tempObj2 = substr(object2::text, 2, length(object2::text) - 2); --remove the first { and last }

    IF object1::text != '{}' and object1::text != 'null' and object1::text != '[]' THEN
        result = ('{' || tempObj1 || ',' || tempObj2 || '}')::jsonb;
    ELSE
        result = ('{' || tempObj2 || '}')::jsonb;
    END IF;
    return result;
end;
$$;

用法:

update table_name
set data = updatejsonb(data, '{"test": "ok"}'::json)

下面的plpython代码片段可能会派上用场。

CREATE EXTENSION IF NOT EXISTS plpythonu;
CREATE LANGUAGE plpythonu;

CREATE OR REPLACE FUNCTION json_update(data json, key text, value text)
 RETURNS json
 AS $$
    import json
    json_data = json.loads(data)
    json_data[key] = value
    return json.dumps(json_data, indent=4)
 $$ LANGUAGE plpythonu;

-- Check how JSON looks before updating

SELECT json_update(content::json, 'CFRDiagnosis.mod_nbs', '1')
FROM sc_server_centre_document WHERE record_id = 35 AND template = 'CFRDiagnosis';

-- Once satisfied update JSON inplace

UPDATE sc_server_centre_document SET content = json_update(content::json, 'CFRDiagnosis.mod_nbs', '1')
WHERE record_id = 35 AND template = 'CFRDiagnosis';

你可以尝试更新如下:

格式:UPDATE table_name SET column_name = column_name::jsonb || '{"key":new_value}' WHERE column_name条件;

举个例子:

UPDATE test SET data = data::jsonb || '{"a":new_value}' WHERE data->>'b' = '2';