如何为 postgresql 中的唯一(不包括顺序)JSONB 列创建约束
Posted
技术标签:
【中文标题】如何为 postgresql 中的唯一(不包括顺序)JSONB 列创建约束【英文标题】:How to create a constraint for unique (not including order) JSONB column in postgresql 【发布时间】:2021-09-23 11:05:45 【问题描述】:我正在寻找一种方法来创建一个约束来验证 JSONB 列中的值是唯一的,但是我需要它们在不考虑顺序的情况下进行比较时也是唯一的,因此 JSONB 比较/散列对这种情况。
为了检查 2 个 JSONB 对象是否相等,我检查它们是否相互包含
select t.a @> t.b and t.a <@ t.b
from (
SELECT
'"foo": 42, "bar": ["value", 5]'::jsonb as a,
'"bar": [5, "value"], "foo": 42'::jsonb as b
) as t
具体来说,我正在寻找一个 SQLAlchemy 解决方案,但原始的 postgresql 解决方案可能会有很大帮助。
【问题讨论】:
JSON 总是一个字符串数组吗? @LaurenzAlbe 否 - 固定示例foo
和 bar
会自动重新排序,但我怀疑有没有好的解决方案。
@LaurenzAlbe 键会自动重新排序,但列表不会?有没有办法在插入时自动重新排序列表?我不需要维护原始排序,但我也不想在应用程序代码中排序
我觉得不错。
【参考方案1】:
我的解决方案是添加一个触发器,该触发器调用一个函数,该函数检查是否已经存在一个 jsonb,该 jsonb 包含并被正在插入的那个包含
触发器:
create trigger trigger1
before insert
on json_table
for each row
execute procedure func;
功能:
create function func returns trigger
language plpgsql
as
$$
declare
same_json json_table%rowtype;
BEGIN
IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
select * from json_table
into same_json
where NEW.json @> json_table.json and NEW.json <@ json_table.json;
IF FOUND then
RAISE NOTICE 'Not inserting json, an equal json is already in the table: id=%', same_json.id;
return NULL;
END IF;
END IF;
RETURN NEW;
END;
$$;
然后我创建了一个手动 alembic 迁移,它添加了触发器和函数 - 请参阅 https://github.com/sqlalchemy/alembic/issues/504#issuecomment-441887901
【讨论】:
以上是关于如何为 postgresql 中的唯一(不包括顺序)JSONB 列创建约束的主要内容,如果未能解决你的问题,请参考以下文章
如何为 PostgreSQL 中的自链接记录设计最佳实践数据结构?
如何为 Postgresql 中的所有数据库创建具有只读权限的用户?
如何为 oracle 中的每个线程选择和阻止行?(PostgreSQL 有一个工作示例)
如何为postgresql中的每个用户返回具有最大值的类别?