Best way to prevent overlapping dates

Started by Andrusalmost 19 years ago5 messagesgeneral
Jump to latest
#1Andrus
kobruleht2@hot.ee

I need to disable rows with overlapping dates in 8.1+
I created the following trigger procedure for this.

Is this best way ?
Will it prevent overlapping rows in all cases ?

Andrus.

create table puhkus (reanr serial primary key, palgus date, plopp date);

CREATE OR REPLACE FUNCTION puhkus_sequenced_pkey() RETURNS trigger AS $$

DECLARE
OverlappingRow INTEGER;

BEGIN
SELECT reanr
INTO OverlappingRow
FROM puhkus
WHERE puhkus.reanr<>NEW.reanr AND doverlaps( puhkus.palgus, puhkus.plopp,
NEW.palgus, NEW.plopp );

IF found THEN
RAISE EXCEPTION 'Changed row % overlaps with existing row %', NEW.reanr,
OverLappingRow ;
END IF;
RETURN NEW;
END;

$$ LANGUAGE plpgsql;

CREATE TRIGGER puhkus_sequenced_trigger BEFORE INSERT OR UPDATE ON puhkus
FOR EACH ROW EXECUTE PROCEDURE puhkus_sequenced_pkey();

CREATE OR REPLACE FUNCTION public.doverlaps(date,
date, date, date, out bool) IMMUTABLE AS
$_$
SELECT coalesce($1, date '0001-01-01')<=coalesce($4, date '9999-12-31') AND
coalesce($2, date '9999-12-31')>=coalesce($3, date '0001-01-01' );
$_$ language sql;

CREATE OR REPLACE FUNCTION PUBLIC.GOMONTH(DATE, INTEGER, OUT DATE) IMMUTABLE
AS
$_$
SELECT ($1 + ($2 * '1 MONTH'::INTERVAL))::DATE;
$_$ LANGUAGE SQL;

I also tried code from SNODGRASS book
"Developing Time-Oriented Database Applications" but this causes error.

create table puhkus (palgus date, plopp date);

alter table puhkus add check
(NOT EXISTS ( SELECT *
FROM puhkus AS I1
WHERE 1 < (SELECT COUNT(*)
FROM puhkus AS I2
WHERE doverlaps(i1.palgus, i1.plopp, i2.palgus, i2.plopp)
) ));

but got error

ERROR: cannot use subquery in check constraint

#2Michael Glaesemann
grzm@seespotcode.net
In reply to: Andrus (#1)
Re: Best way to prevent overlapping dates

On May 25, 2007, at 3:22 , Andrus wrote:

CREATE TRIGGER puhkus_sequenced_trigger BEFORE INSERT OR UPDATE ON
puhkus
FOR EACH ROW EXECUTE PROCEDURE puhkus_sequenced_pkey();

You can also use CREATE CONSTRAINT TRIGGER, which allows you to have
deferrable constraints. This is useful if statements within a
transaction may temporarily put the database in a state where it
violates the constraint: the constraint will be called at the end of
the transaction to make sure integrity is maintained.

http://www.postgresql.org/docs/8.2/interactive/sql-createconstraint.html

create table puhkus (palgus date, plopp date);

alter table puhkus add check
(NOT EXISTS ( SELECT *
FROM puhkus AS I1
WHERE 1 < (SELECT COUNT(*)
FROM puhkus AS I2
WHERE doverlaps(i1.palgus, i1.plopp, i2.palgus, i2.plopp)
) ));

but got error

ERROR: cannot use subquery in check constraint

Right. As the error says, subqueries in CHECK constraints is not
implemented in PostgreSQL.

Michael Glaesemann
grzm seespotcode net

#3Jeff Davis
pgsql@j-davis.com
In reply to: Michael Glaesemann (#2)
Re: Best way to prevent overlapping dates

On Tue, 2007-05-29 at 10:59 -0500, Michael Glaesemann wrote:

On May 25, 2007, at 3:22 , Andrus wrote:

CREATE TRIGGER puhkus_sequenced_trigger BEFORE INSERT OR UPDATE ON
puhkus
FOR EACH ROW EXECUTE PROCEDURE puhkus_sequenced_pkey();

You can also use CREATE CONSTRAINT TRIGGER, which allows you to have
deferrable constraints. This is useful if statements within a
transaction may temporarily put the database in a state where it
violates the constraint: the constraint will be called at the end of
the transaction to make sure integrity is maintained.

http://www.postgresql.org/docs/8.2/interactive/sql-createconstraint.html

The docs say:

"CREATE CONSTRAINT TRIGGER is used within CREATE TABLE/ALTER TABLE and
by pg_dump to create the special triggers for referential integrity. It
is not intended for general use."

Is there harm in using constraint triggers outside of pg_dump? It seems
like deferrable constraints would be useful for many applications, but
the docs imply that it's a bad idea.

Regards,
Jeff Davis

PS: Nice to meet you at PGCon. Hope you enjoyed it as much as I did!

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jeff Davis (#3)
Re: Best way to prevent overlapping dates

Jeff Davis <pgsql@j-davis.com> writes:

Is there harm in using constraint triggers outside of pg_dump? It seems
like deferrable constraints would be useful for many applications, but
the docs imply that it's a bad idea.

It's un-deprecated as of 8.3.

regards, tom lane

#5Michael Glaesemann
grzm@seespotcode.net
In reply to: Jeff Davis (#3)
Re: Best way to prevent overlapping dates

On May 29, 2007, at 12:41 , Jeff Davis wrote:

"CREATE CONSTRAINT TRIGGER is used within CREATE TABLE/ALTER TABLE and
by pg_dump to create the special triggers for referential
integrity. It
is not intended for general use."

Is there harm in using constraint triggers outside of pg_dump? It
seems
like deferrable constraints would be useful for many applications, but
the docs imply that it's a bad idea.

It's a PostgreSQL extension, so it's nonstandard, but my
understanding is that it's safe to use and there are no current plans
to make it go away. As long as you understand what you're doing, I
don't know of any problems with using CREATE CONSTRAINT TRIGGER. I've
asked similar questions in the past, so you might want to check the
archives.

Michael Glaesemann
grzm seespotcode net

PS: Nice to meet you at PGCon. Hope you enjoyed it as much as I did!

It was good to meet you too, Jeff! Hope to see you at the next
gathering :)