定义表中不存在时删除jsonb键

时间:2019-07-05 10:35:55

标签: postgresql

我在一个表(目标)中有一个jsonb字段,而在另一个表(属性)中有该json字段的“允许”键的定义:

CREATE TABLE attributes (name TEXT);
CREATE TABLE target (custom JSONB);

INSERT INTO attributes VALUES ('a'), ('b'), ('c');
INSERT INTO target VALUES ('{"a": "sth", "b": "sth"}'), ('{"c": "sth"}'), ('{"a": "sth", "d": "sth"}');

因此在此简化示例中,允许的键为a,b and c

我现在必须编写一个迁移,该迁移将从target表中删除没有有效定义的键和值。在这种情况下,这将是密钥d

基于此知识,我可以删除d

UPDATE target SET custom = custom - 'd';

但是-如何比较两个表并从target.custom中删除所有键,而在attributes.name中没有键定义呢?

1 个答案:

答案 0 :(得分:1)

您需要首先汇总目标表中每一行应删除的所有键。我假设您在该表中有一些主键列(在下面的示例中为id)。

此查询:

select id, array_agg(ky)
from target
   cross join jsonb_each_text(custom) as c(ky,v)
where c.ky not in (select name from attributes)
group by id;

为每个应删除的ID收集数组中的所有键。现在可以将其用作UPDATE语句的源:

update target 
  set custom = custom - x.keys
from (
  select id, array_agg(ky) as keys
  from target
     cross join jsonb_each_text(custom) as c(ky,v)
     where c.ky not in (select name from attributes)
  group by id
) x
where target.id = x.id;

在线示例:https://www.db-fiddle.com/f/i7VCtjtJVErLwbS88iww7Q/0