Home > Mobile >  Postgres constraint for one "active" case per department
Postgres constraint for one "active" case per department

Time:06-19

I have a situation where a department has many cases, but only 1 case can be active.

In the cases table, there is are department_id: bigint references departments.id and active: boolean columns. How can I set up a unique constraint so that a department could have 3 cases, but only 1 can ever be marked as active: TRUE?

CodePudding user response:

You can use a partial unique constraint:

create unique index on cases (department_id)
where active

CodePudding user response:

You can have 2 simple posibilities:

  1. Make the boolean have only two posibilities: true and null and then set a unique constraint for (department_id, active)
  2. If you can't have only true and null set another column (in a trigger or a calculated column) with the true/null value based in true/false/null column.
  3. Add an unique index over the expression

unique over expresion

create unique index "only one active por department" on cases
  (department_id, (case active when true then true else null end));

Living example: https://onecompiler.com/postgresql/3y7fe9hye

example of calculated column

For alternative 2:

select version();

create table cases(
  department_id integer,
  active boolean,
  value text
);

insert into cases values 
  (1, true, 'a'),
  (1, false, 'b'),
  (1, false, 'c'),
  (2, true, 'd'),
  (2, false, 'e'),
  (2, null, 'f');

-- select * from cases;

alter table cases 
  add column active_true boolean GENERATED ALWAYS 
    AS (case active when true then true else null end) stored;
    
alter table cases
  add unique (department_id, active_true);
  
-- ok:
insert into cases (department_id, active, value) values (1,false, 'g'); 

select * from cases;  

-- fails:
insert into cases (department_id, active, value) values (1,true , 'h'); 

select * from cases;  


obtains:

version                                                           
-----------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.3 (Debian 14.3-1.pgdg110 1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
(1 row)

CREATE TABLE
INSERT 0 6
ALTER TABLE
ALTER TABLE
INSERT 0 1
 department_id | active | value | active_true 
--------------- -------- ------- -------------
             1 | t      | a     | t
             1 | f      | b     | 
             1 | f      | c     | 
             2 | t      | d     | t
             2 | f      | e     | 
             2 |        | f     | 
             1 | f      | g     | 
(7 rows)


psql:commands.sql:32: ERROR:  duplicate key value violates unique constraint "cases_department_id_active_true_key"
DETAIL:  Key (department_id, active_true)=(1, t) already exists.

Live example: https://onecompiler.com/postgresql/3y7exvrvq

  • Related