Reputation: 436
We have a use case where we are storing start_week and end_week in a row and want to make sure that these values across rows are never overlapping i.e. they are exclusive. Examples below
Ideal
code - startw - endw
T1 - 201401 - 201404
T2 - 201405 - 201408
T3 - 201409 - 201416
Not Ideal
code - startw - endw
T1 - 201401 - 201404
T2 - 201403 - 201408
T3 - 201407 - 201408
T3 - 201406 - 201410
Can such a constraint be added in Postgres so errors are caught during insertion? What would be the best approach to tackle such an problem and avoid insertions rather than running checks after data is inserted.
Upvotes: 2
Views: 763
Reputation: 324771
PostgreSQL has a feature designed for exactly this - exclusion constraints.
See CREATE TABLE ... EXCLUDE ...
.
For your purposes you want a constraint on a range. The case you have is covered in the manual.
It's somewhat complicated by your use of a weird format for your dates; you'll need to convert them to a tstzrange for the exclusion constraint.
create table exclude(code text, startw integer, endw integer);
insert into exclude(code, startw, endw) values
('T1', 201401, 201404),
('T2', 201405, 201408),
('T3', 201409, 201416);
You can't just:
alter table exclude
add constraint no_overlapping_timestamps
EXCLUDE USING gist( tstzrange(startw, endw) WITH && );
because you aren't using real timestamps; you have to convert your week numbers to timestamps in the expression above. I can't do that for you because I don't know how you define "week". If it's the standard way, then:
alter table exclude
add constraint no_overlapping_timestamps
EXCLUDE USING gist( tstzrange(to_date(startw, 'YYYYWW'), to_date(endw, 'YYYYWW')) WITH && );
Upvotes: 4