如何在 postgresql 中为唯一(不包括顺序)JSONB 列创建约束

How to create a constraint for unique (not including order) JSONB column in postgresql

我正在寻找一种方法来创建一个约束来验证 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 解决方案可能会有很大帮助。

我的解决方案是添加一个触发器来调用一个函数,该函数检查是否已经有一个 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