Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 使用jsonb_set()更新特定jsonb数组值_Arrays_Json_Postgresql_Sql Update_Jsonb - Fatal编程技术网

Arrays 使用jsonb_set()更新特定jsonb数组值

Arrays 使用jsonb_set()更新特定jsonb数组值,arrays,json,postgresql,sql-update,jsonb,Arrays,Json,Postgresql,Sql Update,Jsonb,目前我正在使用PostgreSQL 9.5,并尝试更新jsonb字段数组中的值。但我无法获取所选值的索引 我的桌子就像这样: CREATE TABLE samples ( id serial, sample jsonb ); {"result": [ {"8410": "ABNDAT", "8411": "Abnahmedatum"}, {"8410

目前我正在使用PostgreSQL 9.5,并尝试更新jsonb字段数组中的值。但我无法获取所选值的索引

我的桌子就像这样:

 CREATE TABLE samples (
    id serial,
    sample jsonb
 );
{"result": [
    {"8410": "ABNDAT", "8411": "Abnahmedatum"},
    {"8410": "ABNZIT", "8411": "Abnahmezeit"},
    {"8410": "FERR_R", "8411": "Ferritin"}
]}
我的JSON如下所示:

 CREATE TABLE samples (
    id serial,
    sample jsonb
 );
{"result": [
    {"8410": "ABNDAT", "8411": "Abnahmedatum"},
    {"8410": "ABNZIT", "8411": "Abnahmezeit"},
    {"8410": "FERR_R", "8411": "Ferritin"}
]}
我的SELECT语句可以获得正确的值:

SELECT 
    id, value 
FROM 
    samples s, jsonb_array_elements(s.sample#>'{result}') r  
WHERE 
    s.id = 26 and r->>'8410' = 'FERR_R';
结果:

id | value
----------------------------------------------
26 | {"8410": "FERR_R", "8411": "Ferritin"}
好的,这就是我想要的。现在,我想使用以下update语句执行更新,以添加新元素“ratingtext”(如果还没有):

执行UPDATE语句后,我的数据如下所示(同样正确):

到目前为止还不错,但我手动搜索了索引值2,以获得JSON数组中的正确元素。如果要更改订单,这将不起作用

所以我的问题是:

有没有办法获取所选JSON数组元素的索引,并将SELECT语句和UPDATE语句合并为一个

就像:

UPDATE 
    samples s
SET
    sample = jsonb_set(sample,
              '{result,' || INDEX OF ELEMENT || ',ratingtext}',
              '"Some individual text"'::jsonb,
              true)
WHERE
      s.id = 26;
在准备语句之前,samples.id和“8410”的值是已知的


或者这在目前是不可能的?

您可以使用具有顺序性的
jsonb_数组_elements()(注意,
ordinality
从1开始,而json数组的第一个索引是0):

使用上面的查询根据元素的索引更新元素(注意
jsonb_set()
的第二个参数是文本数组):

结果:

select id, jsonb_pretty(sample)
from samples;

 id |                   jsonb_pretty                   
----+--------------------------------------------------
 26 | {                                               +
    |     "result": [                                 +
    |         {                                       +
    |             "8410": "ABNDAT",                   +
    |             "8411": "Abnahmedatum"              +
    |         },                                      +
    |         {                                       +
    |             "8410": "ABNZIT",                   +
    |             "8411": "Abnahmezeit"               +
    |         },                                      +
    |         {                                       +
    |             "8410": "FERR_R",                   +
    |             "8411": "Ferritin",                 +
    |             "ratingtext": "Some individual text"+
    |         }                                       +
    |     ]                                           +
    | }
(1 row)
jsonb_set()
中的最后一个参数应该是
true
,以便在其键不存在时强制添加新值。但是,它可能会被跳过,因为它的默认值是
true


虽然并发问题似乎不太可能出现(由于限制性的WHERE条件和可能受影响的行数较少),但您可能也对

感兴趣,非常感谢您的回答!它就像一个魔咒!我没有意识到,我可以在WHERE子句中使用elem。谢谢klin,这刚刚救了我一天!通过将其分解为多个部分很好地解释了这一点,这值得更多的投票sure@klin,缺少的一点可能是潜在的并发性问题,请参见,为什么在
jsonb_set
中使用
true
?@christoroussy-谢谢,我添加了相应的注释。类似的问题/答案:
update 
    samples
set
    sample = 
        jsonb_set(
            sample,
            array['result', elem_index::text, 'ratingtext'],
            '"some individual text"'::jsonb,
            true)
from (
    select 
        pos- 1 as elem_index
    from 
        samples, 
        jsonb_array_elements(sample->'result') with ordinality arr(elem, pos)
    where
        id = 26 and
        elem->>'8410' = 'FERR_R'
    ) sub
where
    id = 26;    
select id, jsonb_pretty(sample)
from samples;

 id |                   jsonb_pretty                   
----+--------------------------------------------------
 26 | {                                               +
    |     "result": [                                 +
    |         {                                       +
    |             "8410": "ABNDAT",                   +
    |             "8411": "Abnahmedatum"              +
    |         },                                      +
    |         {                                       +
    |             "8410": "ABNZIT",                   +
    |             "8411": "Abnahmezeit"               +
    |         },                                      +
    |         {                                       +
    |             "8410": "FERR_R",                   +
    |             "8411": "Ferritin",                 +
    |             "ratingtext": "Some individual text"+
    |         }                                       +
    |     ]                                           +
    | }
(1 row)