我对 Postgres 的范围类型有点陌生,我可以在以下方面寻求您的帮助:
一个人的出生日期和死亡日期需要记录在带有
daterange
的表格中。为了防止无效数据,我在表定义中添加了约束alive_bounds
:
create table person (
id bigserial not null,
alive daterange not null,
name text not null,
constraint id_pkey primary key (id),
constraint alive_bounds check (
lower(alive) != 'infinity' and
lower(alive) != '-infinity' and
lower(alive) is not null and
upper(alive) != 'infinity' and
upper(alive) != '-infinity' and
(coalesce(upper(alive), current_date)::timestamp
- lower(alive)::timestamp) < interval '120 years'
)
);
insert into person (alive, name) values (daterange(current_date, null), 'Some One');
insert into person (alive, name) values (daterange('1900-01-01', null), 'Another One');
输出:
INSERT 0 1
ERROR: new row for relation "person" violates check constraint "alive_bounds"
DETAIL: Failing row contains (2, [1900-01-01,), Another One).
除了文档中有关恢复数据并使用 trigger
的警告
之外,数据可能会随着时间的推移而损坏。例如,200 年内,ID 为
1
的人将会死亡。为了测试 Postgres 如何处理这种情况,我重新创建了表,并将间隔设置为 1 秒。但是,当我再次插入 person
1
时,Postgres 在间隔到期后不会给我任何警告,例如当我
select
数据时。触发检查和此检查约束有什么区别? 有什么更好的解决方案来存储两个日期并让 Postgres 发出一些关于范围值无效或变得无效的警告?
什么是正确的做法取决于如果时间过去导致该行变得无效,您希望该行发生什么情况。
ALTER TABLE person ENABLE ROW LEVEL SECURITY;
ALTER TABLE person FORCE ROW LEVEL SECURITY;
CREATE POLICY vanish_old ON person
FOR ALL TO PUBLIC
USING (coalesce(upper(alive), current_date) -
lower(alive) < 43830);
行保留在表中,因此如果行数很多,这不是一个好的解决方案。