And*_*iuk 11 postgresql exclusion-constraint
想象一下你有一个简单的表:
name | is_active
----------------
A | 0
A | 0
B | 0
C | 1
... | ...
Run Code Online (Sandbox Code Playgroud)
我需要创建一个特殊的唯一约束,该约束在以下情况下失败:相同is_active
值不能共存不同的name
值。
允许条件示例:
注意:简单的多列唯一索引不允许这样的组合。
A | 0
A | 0
B | 0
Run Code Online (Sandbox Code Playgroud)
允许条件示例:
A | 0
B | 1
Run Code Online (Sandbox Code Playgroud)
失败条件示例:
A | 0
A | 1
-- should be prevented, because `A 0` exists
-- same name, but different `is_active`
Run Code Online (Sandbox Code Playgroud)
理想情况下,我需要唯一约束或唯一部分索引。触发器对我来说更成问题。
双重A,0
允许,但(A,0) (A,1)
不是。
ype*_*eᵀᴹ 19
您可以使用排除约束btree_gist
,
-- This is needed
CREATE EXTENSION btree_gist;
Run Code Online (Sandbox Code Playgroud)
然后我们添加一个约束,说:
“我们不能有 2 行具有相同name
和不同的is_active
”:
ALTER TABLE table_name
ADD CONSTRAINT only_one_is_active_value_per_name
EXCLUDE USING gist
( name WITH =,
is_active WITH <> -- if boolean, use instead:
-- (is_active::int) WITH <>
);
Run Code Online (Sandbox Code Playgroud)
一些注意事项:
is_active
可以是整数或布尔值,对排除约束没有区别。(实际上确实如此,如果列是布尔值,则需要使用(is_active::int) WITH <>
.)name
或is_active
为空将被限制被忽略,从而允许。UNIQUE
约束(name)
会更容易也更合适。我没有看到存储多个相同行的任何理由。name = 'A'
并且想要将 is_active 状态从 0 更新为 3,则必须更新所有 1000 行。您应该检查规范化设计是否会更有效。(在这种情况下,规范化含义是从表中删除 is_active 状态并添加名称为 is_active 的 2 列表和对 的唯一约束(name)
。如果is_active
是布尔值,则可以完全剥离它,而额外的表只是一个单列表,存储只有“活动”名称。) 归档时间: |
|
查看次数: |
2756 次 |
最近记录: |