vek*_*tor 5 postgresql database-design exclusion-constraint unique-constraint
我正在使用 PostgreSQL 9.3。假设我们正在制造某种类型的某些物品,在任何时候我们最多只能生产某种类型的一件物品。下表记录了我们制造物品的历史记录,其中可能有一行manufactured_until是null- 这些是当前生产的物品。
create table item
(
id int,
type_id int,
manufactured_from timestamp,
manufactured_until timestamp
)
Run Code Online (Sandbox Code Playgroud)
样本数据:
1 | 101 | 1.1.2000 | 31.12.2012
2 | 102 | 1.4.2003 | 1.1.2010
3 | 101 | 1.1.2013 |
4 | 102 | 2.1.2010 | 4.5.2014
5 | 102 | 5.5.2014 |
Run Code Online (Sandbox Code Playgroud)
以下逻辑应该成立:对于每种物品类型,此时最多应该生产一个物品 ( manufactured IS NULL)。在示例中,我应该无法添加记录(6, 101, 27.8.2014, NULL)。
我想写一个UNIQUE约束来保护它。是否可以?对于奖励积分,是否有一种相当复杂的方法来保护一种项目类型的间隔不重叠?
部分唯一索引应该这样做:
create unique index max_one_null
on item (type_id)
where manufactured_until is null;
Run Code Online (Sandbox Code Playgroud)
对于奖励积分,是否有一种相当复杂的方法来保护一种项目类型的间隔不重叠
查看范围类型和排除约束。它们是专门为这个问题设计的。
像这样的东西(未经测试):
create table item
(
id int,
type_id int,
manufactured_during tsrange
);
Run Code Online (Sandbox Code Playgroud)
插入内容看起来有点不同,因为现在只有一列:
insert into item
(id, type_id, manufactured_during)
values
(1, 101, '[2000-01-01,2012-12-31]'),
(1, 101, '[2013-01-01,)');
Run Code Online (Sandbox Code Playgroud)
[2000-01-01,2012-12-31]定义一个包含两个日期的闭区间。[2013-01-01,)定义一个没有结束的开放区间(映射到manufactured_until is null您当前的表设计)
然后添加一个排除约束来保护范围:
alter table item
add constraint check_manufactured_range
exclude using gist (type_id with =, manufactured_during with &&);
Run Code Online (Sandbox Code Playgroud)
您不再需要唯一索引,因为约束将确保没有任何内容重叠。
手册中的更多信息:http : //www.postgresql.org/docs/current/static/rangetypes.html
如果您在 Internet 上搜索“Postgres 排除约束”,您将找到一些关于此主题的演示文稿和博客文章。
PS:似乎您实际上想要一个daterange(而不是“时间戳范围”),因为您可能不想将一天中的时间包含在定义某物制造时间的间隔中。
| 归档时间: |
|
| 查看次数: |
2158 次 |
| 最近记录: |