使用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...

当前回答

例如,我的字符串是这样的: {" a1 ":{“a11”:“x”,“a22”:“y”、“a33”:“z”}}

我使用临时表更新jsons,这对于相当小的数据量(<1.000.000)已经足够了。我找到了另一条路,但后来去度假了,就忘了……

所以。查询将是这样的:

with temp_table as (
select 
a.id,
a->'a1'->>'a11' as 'a11',
a->'a1'->>'a22' as 'a22',
a->'a1'->>'a33' as 'a33',
u1.a11updated
from foo a
join table_with_updates u1 on u1.id = a.id)
    update foo a
    set a = ('{"a1": {"a11": "'|| t.a11updated ||'",
        "a22":"'|| t.a22 ||'",
        "a33":"'|| t.a33 ||'"}}')::jsonb
    from temp_table t
    where t.id = a.id;

它与string的关系比json更大,但它是有效的。基本上,它将所有数据拉到临时表中,在用备份的数据插入concat漏洞时创建一个字符串,并将其转换为jsonb。

Json_set可能更有效,但我仍然掌握了它的窍门。当我第一次尝试使用它时,我完全把弦弄乱了……

其他回答

在Postgresql 9.5中,可以执行以下命令-

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

OR

UPDATE test
SET data = jsonb_set(data, '{a}', '5'::jsonb);

有人问如何一次更新jsonb值中的多个字段。假设我们创建一个表:

CREATE TABLE testjsonb ( id SERIAL PRIMARY KEY, object JSONB );

然后我们插入一个实验行:

INSERT INTO testjsonb
VALUES (DEFAULT, '{"a":"one", "b":"two", "c":{"c1":"see1","c2":"see2","c3":"see3"}}');

然后我们更新行:

UPDATE testjsonb SET object = object - 'b' || '{"a":1,"d":4}';

它的作用如下:

更新a字段 删除b字段 添加d字段

选择数据:

SELECT jsonb_pretty(object) FROM testjsonb;

会导致:

      jsonb_pretty
-------------------------
 {                      +
     "a": 1,            +
     "c": {             +
         "c1": "see1",  +
         "c2": "see2",  +
         "c3": "see3",  +
     },                 +
     "d": 4             +
 }
(1 row)

要更新里面的字段,不要使用concat操作符||。请改用jsonb_set。这并不简单:

UPDATE testjsonb SET object =
jsonb_set(jsonb_set(object, '{c,c1}','"seeme"'),'{c,c2}','"seehim"');

使用concat操作符{c,c1},例如:

UPDATE testjsonb SET object = object || '{"c":{"c1":"seedoctor"}}';

将移除{c,c2}和{c,c3}。

要获得更强大的功能,请查看postgresql json函数文档。有人可能会对#-操作符、jsonb_set函数和jsonb_insert函数感兴趣。

对于那些使用mybatis的人,这里有一个更新语句示例:

<update id="saveAnswer">
    update quiz_execution set answer_data = jsonb_set(answer_data, concat('{', #{qid}, '}')::text[], #{value}::jsonb), updated_at = #{updatedAt}
    where id = #{id}
</update>

参数:

Qid, field的键。 是一个有效的json字符串,对于字段值, 通过jackson将对象转换为json字符串,

我发现以前的答案更适合有经验的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)

这个解决方案是jsonb_set的替代方案,即使JSONB的列中有NULL,它也能工作。只有当对象存在时,jsonb_set才有效。

在下面的示例中,settings是用户表上的JSONB列。

 UPDATE public."Users"
 SET settings = coalesce("settings", '{}')::jsonb || '{ "KeyToSet" : "ValueToSet" }'
 WHERE id=35877;