sql - PostgreSQL:从 JSON 列中删除属性

标签 sql json postgresql postgresql-json

我需要从 json 类型列中删除一些属性。

table :

CREATE TABLE my_table( id VARCHAR(80), data json);
INSERT INTO my_table (id, data) VALUES (
  'A', 
  '{"attrA":1,"attrB":true,"attrC":["a", "b", "c"]}'
);

现在,我需要从 data 列中删除 attrB

alter table my_table drop column data->'attrB'; 这样的东西会很好。但是使用临时表的方法也足够了。

最佳答案

更新:对于 9.5+,您可以将显式运算符与 jsonb 一起使用(如果您有 json 类型的列,则可以使用强制转换来应用修改):

可以使用 - 操作符从 JSON 对象(或数组)中删除键(或索引):

SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
       jsonb '["a",1,"b",2]' - 1    -- will yield jsonb '["a","b",2]'

可以使用 #- 运算符从 JSON 层次结构的深处删除:

SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'

对于 9.4,您可以使用原始答案的修改版本(如下),但您可以直接使用 json_object_agg() 聚合成一个 json 对象,而不是聚合 JSON 字符串.

相关:PostgreSQL 中的其他 JSON 操作:

原答案(适用于 PostgreSQL 9.3):

如果您至少有 PostgreSQL 9.3,您可以使用 json_each() 将对象分成对并过滤不需要的字段,然后再次手动构建 json。比如:

SELECT data::text::json AS before,
       ('{' || array_to_string(array_agg(to_json(l.key) || ':' || l.value), ',') || '}')::json AS after
FROM (VALUES ('{"attrA":1,"attrB":true,"attrC":["a","b","c"]}'::json)) AS v(data),
LATERAL (SELECT * FROM json_each(data) WHERE "key" <> 'attrB') AS l
GROUP BY data::text

对于 9.2(或更低版本),这是不可能的。

编辑:

更方便的形式是创建一个函数,它可以移除一个json字段中任意数量的属性:

编辑 2:string_agg()array_to_string(array_agg())

便宜
CREATE OR REPLACE FUNCTION "json_object_delete_keys"("json" json, VARIADIC "keys_to_delete" TEXT[])
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT COALESCE(
  (SELECT ('{' || string_agg(to_json("key") || ':' || "value", ',') || '}')
   FROM json_each("json")
   WHERE "key" <> ALL ("keys_to_delete")),
  '{}'
)::json
$function$;

使用此功能,您只需运行以下查询:

UPDATE my_table
SET data = json_object_delete_keys(data, 'attrB');

关于sql - PostgreSQL:从 JSON 列中删除属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23490965/

相关文章:

json - 如何从JSON创建CSV输出?

postgresql - 使用多个连接和分组优化 SQL 查询 (Postgres 9.3)

PostgreSQL 9.3 SQL 结果 : long text has shortened

A、B 和 C 之间的 SQL JOIN 混合全连接和左连接

mysql - 如何选择在两列中具有相同值集的行,从而连接第三列中的值?

sql - JOIN或带有exists子句的Correlated子查询,哪个更好

python - 我收到 KeyError : '563690668808208423' when i'm trying to add exp to user

python - 值错误: too many values to unpack with JSON File and Requests Post Call

php - 敏捷并行数据库迁移

MySQL 查询 - 1 列上的多个 WHERE 子句