4

PostgreSQL 是否提供任何符号/方法来对JSON 数组的每个元素施加约束?

一个例子:

create table orders(data json);

insert into orders values ('
{
    "order_id": 45,
    "products": [
        {
            "product_id": 1,
            "name": "Book"
        },
        {
            "product_id": 2,
            "name": "Painting"
        }
    ]
}
');

我可以轻松地在字段上添加约束order_id

alter table orders add check ((data->>'order_id')::integer >= 1);

现在我需要对product_id. 我可以对单个数组项施加约束:

alter table orders add check ((data->'products'->0->>'product_id')::integer >= 1);
alter table orders add check ((data->'products'->1->>'product_id')::integer >= 1);
-- etc.

所以很明显我正在寻找的是某种用于匹配任何 JSON 数组元素的通配符运算符:

alter table orders add check ((data->'products'->*->>'product_id')::integer >= 1);
--                                               ^ like this

我知道这可以通过将产品提取到products具有外键的单独表中来完成orders。但我想知道这是否可以在单个 JSON 列中实现,因此在设计数据库模式时可以牢记这一点。

4

2 回答 2

3

所以我按照Craig Ringer 的建议在 PostgreSQL mailing list 上问了这个问题,我得到了答案。

简而言之,解决方案是编写一个将 JSON 数组具体化为 PostgreSQL 数组的过程:

create function data_product_ids(JSON) returns integer[] immutable  as $$
select array_agg((a->>'product_id')::integer) from
json_array_elements($1->'products') as a $$ language sql ;

CHECK并在声明中使用该程序:

alter table orders add check (1 <= ALL(data_product_ids(data)));

有关其工作原理的更多详细信息,请参阅PostgreSQL 邮件列表上的答案。归功于乔尔霍夫曼。

于 2014-02-16T10:45:56.450 回答
1

来自 Postgres 的 JSON 开发人员之一

路径的东西不支持通配符。

于 2014-01-21T19:39:53.773 回答