【问题标题】:Is it possible to add a constraint to check every inserted object into a JSON array using Postgres?是否可以添加约束以使用 Postgres 将每个插入的对象检查到 JSON 数组中?
【发布时间】:2019-10-16 07:07:15
【问题描述】:

我试图弄清楚如何在 Postgres 中向包含 JSON 对象的表添加约束。我希望该约束确保 jpg 将具有非 null md5 属性。

我试图检查子数组,但无法让它在数组上工作。如果使用取消引用箭头运算符(table->'jpg'->0 ?'md5'),我可以测试该属性。我也尝试过使用 jsonb_array_elements() 函数,但它不允许在约束语句中使用。

例如:

{
    jpg: [
        {
            md5: "some md5",
            ...
        }
    ]
}

我会用这个:

ALTER TABLE table ADD CONSTRAINT md5_is_defined CHECK(table->'jpg'->0 ? 'md5')

但我不想只检查第一个插入的元素

我想知道在这个检查语句中使用 jsonb_array_elements 是否有一些技巧。是的,我意识到我应该标准化我的数据。我试图这样做,但为它编写语句变成了一个怪物。

【问题讨论】:

  • "我尝试过这样做,但是为它编写语句变成了一个怪物" 所以你更喜欢编写每次需要时取消嵌套和重新聚合数组的怪物更改该数组中的单个项目?为什么 md5 还是在数组中?您是否希望每个 jpg 有多个 md5 值?
  • 这只是一个随意的例子。我没有使用这种数据结构。我正在使用一个具有许多可选字段(30+?)和更多其他字段的字段,在我有限的经验中,它变得非常头疼。我宁愿这样做,因为数据库大小会很小并且性能并不重要。这是一个主要用于学习的爱好项目。

标签: arrays postgresql constraints jsonb


【解决方案1】:

在 SQL 中处理数组非常麻烦,因为它们基本上违反了 SQL 所做的任何事情。检查数组中的每个元素是否存在某些东西通常强烈表明数组是错误的选择。

使用 Postgres 12,这非常容易做到:

alter table the_table 
    add constraint md5_is_defined 
    check (jsonb_path_exists(the_column, '$.jpg[*].md5'));

对于旧版本,我唯一能想到的就是创建一个检查存在的函数,然后在检查约束中使用该函数:

create or replace function check_md5(p_input jsonb)
  returns boolean
as
$$
select exists (select *
               from jsonb_array_elements(p_input -> 'jpg') as t(e) 
               where e ? 'md5');
$$
language sql
immutable;

那么你可以这样使用它:

alter table the_table 
    add constraint md5_is_defined 
    check (check_md5(the_column));

编辑

要检查特定键是否包含非空数组,您可以使用以下内容:

alter table the_table
    add constraint non_empty_array
    check (jsonb_path_exists(the_column, '$.event ? (@.teams.type() == "array" && @.teams.size() > 0)'));

检查@.teams.type() == "array" 是必要的,因为简单的{"teams": "yes"} 也会为size() 返回一个非零值

【讨论】:

  • 我升级到了12。可以检查数组长度吗?我可以做顶级阵列没问题,但我无法找出一个子阵列。 jsonb_array_length(event->'teams') > 0 例如工作正常,我尝试使用 json 路径查询,但它说它不允许在检查语句中。
  • @kmm3:请参阅可能编辑(作为未来问题的旁注:一旦您有答案,通常不认为是扩大问题范围的好做法)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
相关资源
最近更新 更多