在PostgreSQL中创建约束时,有没有办法解决JSON数组的所有元素?

时间:2014-01-20 23:07:01

标签: json postgresql postgresql-9.3

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列中是否可以实现这一点,因此在设计数据库模式时我可以牢记这一点。

2 个答案:

答案 0 :(得分:3)

所以我问this question on PostgreSQL mailing listsuggested by Craig Ringer,我得到了答案。

简而言之,解决方案是编写一个将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)));

有关其工作原理的详细信息,请the answer on PostgreSQL mailing list。致Joel Hoffman的信用。

答案 1 :(得分:0)

来自JSON for Postgres的一位开发人员

  

路径内容不支持通配符。