首页 > 解决方案 > 组之间的 SQL (PostgreSQL) 唯一值

问题描述

我有一个包含 val_A、val_B 列的表。要求我只能插入(没有更新/删除,我想避免触发器和存储过程)。

我如何实现这样的要求,即列 val_A 的值必须是唯一的,但不是整个表,而是基于 val_B 的组。换句话说,对于 val_B = 1,我可以有许多 val_A = 1 的条目,但在这种情况下,我不能让 val_A = 1 和 val_B != 1;

例如:

+-------+-------+---------------------+
| val_A | val_B |       Comment       |
+-------+-------+---------------------+
|     1 |     1 |                     |
|     2 |     1 |                     |
|     1 |     1 | This is Allowed     |
|     1 |     2 | This is not allowed |
+-------+-------+---------------------+

编辑#1 我正在寻找的解决方案应该适用于当前的插入。我正在尝试类似于Davide Anghileri响应的东西,但在并发插入场景中失败了。

标签: sqlpostgresqlwhere-clauseunique-index

解决方案


NULL这很棘手,但您可以在表达式上创建唯一索引 - 并使用 Postgres 允许值在唯一索引中重复的事实。

所以:

create unique index unq_t_val_a_val_b on
    (case when val_a <> val_b then least(val_a, val_b) end,
     case when val_a <> val_b then greatest(val_a, val_b) end
    );

当值least()同时,然后greatest()创建一个索引,其中包含两个键,值按顺序排列。当值相同时,键是这样的,NULL因此它们实际上并不是唯一索引的一部分。

你也可以通过过滤来做到这一点:

create unique index unq_t_val_a_val_b on
    (least(val_a, val_b), greatest(val_a, val_b))
    where val_a <> val_b;

推荐阅读