postgresql - 在 JSONB 数组中插入元素 - Postgresql

标签 postgresql sql-update jsonb postgresql-10

假设我有一张 table :

SELECT * FROM settings;
| id | name    | strategies |
| -- | ---     | ---        |
| 1  | default | [{name: xyz, enabled: true}, {name: bot2, enabled: true}]  |
| 2  | new1    | [{name: bot2, enabled: true}, {name: xyz, enabled: false}] |

我想在 bot2 之前添加一个新对象 {name: bot1, enabled: true}

我正在尝试使用来自 this answered question 的解决方案:

WITH bot2_index AS (SELECT
    pos- 1 AS bot2_index
FROM
    settings, 
    jsonb_array_elements(strategies) WITH ordinality arr(elem, pos)
WHERE
    NAME = 'default'
    AND elem->>'name' = 'bot2')    
UPDATE settings
SET strategies = jsonb_set(strategies, '{bot2_index}', '{
  "name": "bot1",
  "enabled": false
}', TRUE);

但是我明白了

ERROR:  path element at position 1 is not an integer: "bot2_index"

bot2_indexbigint 类型那么为什么这个语法不起作用?

我还尝试了其他变体,例如 bot2_indexbot2_index::intbot2_index::string,甚至可以将其运行为两个单独的查询(就像在接受的答案中一样)但它也不起作用。

编辑#1

此语法有效,但它似乎替换了该索引处的元素,而不是在给定索引处的元素之前或之后附加元素 - 我怎样才能让它像 JS splice()功能?

UPDATE settings
SET strategies = jsonb_set(strategies, concat('{',(SELECT
    pos- 1 AS bot2_index
FROM
    settings, 
    jsonb_array_elements(strategies) WITH ordinality arr(elem, pos)
WHERE
    NAME = 'default'
    AND elem->>'name' = 'js:bot2'),'}')::text[], '{
  "name": "bot1",
  "enabled": false
}', TRUE);

最佳答案

首先,对于您当前的查询,您应该像下面这样使用它:

WITH bot2_index AS (SELECT
    pos- 1 AS bot2_index
FROM
    settings, 
    jsonb_array_elements(strategies) WITH ordinality arr(elem, pos)
WHERE
    name = 'default'
    AND elem->>'name' = 'bot2')    
        
UPDATE settings
SET strategies = jsonb_set(strategies, array[bot2_index::text], '{
  "name": "bot1",
  "enabled": false
}'::jsonb, false) from bot2_index;

但查询将替换现有的 DEMO

你应该使用 jsonb_insert 而不是 jsonb_set

WITH bot2_index AS (SELECT
    pos- 1 AS bot2_index
FROM
    settings, 
    jsonb_array_elements(strategies) WITH ordinality arr(elem, pos)
WHERE
    name = 'default'
    AND elem->>'name' = 'bot2')    
        
UPDATE settings
SET strategies = jsonb_insert(strategies, array[bot2_index::text], '{
  "name": "bot1",
  "enabled": false
}'::jsonb, false) from bot2_index;
  

DEMO

关于postgresql - 在 JSONB 数组中插入元素 - Postgresql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63032438/

相关文章:

string - 如何在postgresql中获取一列字符串的字符串长度

postgresql - 即时选择 DISTINCT 和 TRIM

MySQL 根据另一个表值更新表

sql - 将包含 JSONB 字符串数组的行拆分为两个不同的行 (PostgreSQL)

postgresql - 在 PostgreSQL 中搜索嵌套的 jsonb 数组

postgresql - Postgres jsonb_set 连接当前值

python - 从表中删除所有数据,但最后 N 个条目

postgresql - 仅返回数组包含元素的第一行,并可能遗漏之前看到的任何元素

MYSQL移动平均计算优先级无限制

SQL Server 2008 使用联接表中的联接和 Where 子句更新查询