0

How to write a constraint (table level unique, using GIST and or EXCLUDE ) to perform duplication record validation using the following rule:

  1. Entered from_date and to_date values should not be equal or within the range, and
  2. Employee_id should not be equal, and

After the validation, an error message should be return saying 'Duplicate Entry'. This is in postgreSQL.

Note: I am new to postgreSQL (worked in MS SQL Server and MySQL).

Thanks in advance.

6
  • "should not be equal or within the range" - within which range? Commented Nov 15, 2021 at 7:00
  • This is like a duplication checking, entered from_date and to_date values should not be equal or within the range of existing values of from_date and to_date columns. employee_id should not be equal to the existing employee_id value. Commented Nov 15, 2021 at 7:03
  • That description is not clear. Anyway, I think that the third condition (though its meaning isn't clear) will make it impossible to do that with a constraint. Commented Nov 15, 2021 at 7:13
  • A entry or a record will be considered as a duplicate when an entered from_date and to_date values are equal or within the range of the existing from_date and to_date columns values AND entered employee_id should not be equal to existing employee_id value AND the entered values for the status column should not be equal to the value 'pending'. Commented Nov 15, 2021 at 7:48
  • The non-overlapping ranges for an employee_id can easily be done using an exclusion constraint, but as Laurenz already mentioned doing that only for pending events can't be done with an exclusion constraint - only with a filtered unique index. But that in turn doesn't support exclusion constraints. So the combination of all three doesn't really seem possible. What would be possible is to prevent overlapping ranges for an employee_id with the same status (so no overlapping pending, no overlapping "final" etc) Commented Nov 15, 2021 at 7:51

1 Answer 1

1

As stated by @Laurenz Albe, it sounds like impossible to do with a constraint. You can implement either a trigger function or a rule instead :

Trigger function :

CREATE OR REPLACE FUNCTION test_insert_table()
RETURNS trigger LANGUAGE plpgsql IMMUTABLE AS
$$
BEGIN
IF NEW.status = 'pending'
AND EXISTS
  ( SELECT 1
      FROM your_table
     WHERE Employee_id = NEW.Employee_id
       AND range @> daterange(NEW.from_date, NEW.to_date)
  )
THEN
  RAISE EXCEPTION 'Duplicate Entry' ;
  RETURN NULL ;
ELSE
  RETURN NEW ;
END IF ;
END ;
$$

CREATE OR REPLACE TRIGGER test_insert_table 
BEFORE INSERT ON your_table
FOR EACH ROW EXECUTE FUNCTION test_insert_table() ;

Rule :

CREATE OR REPLACE RULE test_insert AS
    ON INSERT TO your_table
 WHERE NEW.status = 'pending'
   AND EXISTS
       ( SELECT 1
           FROM your_table
          WHERE Employee_id = NEW.Employee_id
            AND range @> daterange(NEW.from_date, NEW.to_date)
       )
    DO INSTEAD NOTHING ;
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you 'Edouard', since the application wants the error message, we decided to have it in the trigger. Your answer helped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.