如何在 postgresql 中对 json 类型使用唯一约束

Posted

技术标签:

【中文标题】如何在 postgresql 中对 json 类型使用唯一约束【英文标题】:How to use unique constraint for json type in postgresql 【发布时间】:2018-11-05 05:17:42 【问题描述】:

如何在 postgresql 中为“json”列设置唯一约束?唯一对我来说意味着:如果每个键匹配并且 json 对象的每个值都匹配,则 json 对象是唯一的。

【问题讨论】:

【参考方案1】:

这对于您有些过时的 9.4 版本是不可能的

Postgres 9.5 引入了一种不同的 JSON 类型,名为 jsonb,它确实支持相等运算符。因此,如果您真的非常需要这个,您将不得不升级到更新的版本(例如 10 或 11)

json 数据类型保留了输入值的顺序,因此使比较变得非常复杂(至少效率不高)。

jsonb 类型规范化键/值并将数据存储为二进制 格式,可实现有效的相等性检查。

例如

'"foo": 42, "bar": "value"'::jsonb = '"bar": "value", "foo": 42'::jsonb

返回true。转换为 json 的相同表达式会导致错误。

所以下面的 DDL 有效:

create table data 
(
  id        serial primary key,
  payload   jsonb,
  unique (payload)
);

但是,索引条目的大小是有限制的(大约 2000 字节)。因此,向这样的表中插入数据失败的情况可能不是因为违反了唯一约束,而是因为 JSON 值太大。


Postgres 9.4 的一个选项是在 JSON 值的 MD5 散列上创建一个唯一索引。

create unique index on data ( md5(payload::text) );

但这在您始终以完全相同的顺序指定 JSON 中的键时才有效。因为'"foo": 42, "bar": "value"' 的 md5 哈希值与 '"bar": "value", "foo": 42' 的 md5 哈希值不同


一些关于索引大文本值的解决方案的问题:

https://dba.stackexchange.com/questions/144575 https://dba.stackexchange.com/questions/69161 https://dba.stackexchange.com/questions/69170 https://dba.stackexchange.com/questions/217087/

【讨论】:

鉴于情况我将切换到jsonb:有没有有效的方法来克服索引大小的限制?我可以在没有“正确顺序”限制的情况下为 jsonb 使用哈希吗? Can I use a hash for jsonb without the "right order" limitation? 根据散列函数的定义,没有。

以上是关于如何在 postgresql 中对 json 类型使用唯一约束的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Postgresql 中添加、更新和删除 Json 数据类型?

如何在 laravel 中获取 PostgreSQL 的 JSON 类型数据?

如何在 Postgres 9.4 中对 JSONB 类型的列执行更新操作

如何修改新 PostgreSQL JSON 数据类型中的字段?

如何在 PostgreSQL 中对列的一部分进行分组?

如何使用新的 PostgreSQL JSON 数据类型中的字段进行查询?