定义表中不存在时删除 jsonb 键
Posted
技术标签:
【中文标题】定义表中不存在时删除 jsonb 键【英文标题】:Delete jsonb keys when not present in a definition table 【发布时间】:2019-07-05 10:35:55 【问题描述】: https://www.db-fiddle.com/f/kYghNDHwSXVKZ6uMredofZ/0 PostgreSQL 10我在一个表(目标)中有一个 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】:您需要首先汇总目标表中每一行应删除的所有键。我假设您在该表中有一些主键列(在我的以下示例中为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
【讨论】:
这行得通,谢谢!您的示例与我的示例相同(可能是复制+粘贴错误)。我用 id 创建了一个新的:db-fiddle.com/f/kYghNDHwSXVKZ6uMredofZ/1以上是关于定义表中不存在时删除 jsonb 键的主要内容,如果未能解决你的问题,请参考以下文章