5

Table: Relatives

  • emp_id
  • dep_id(composite primary key)

We have to restrict one employee to three dependents.

Mahmoud Gamal
  • 78,257
  • 17
  • 139
  • 164
Pop Stack
  • 926
  • 4
  • 19
  • 27

2 Answers2

9

This cannot be done using a check constraint alone, but there is a way using a materialized view and a check constraint as I demonstrate here on my blog. For your example this would be:

create materialized view emp_dep_mv
build immediate
refresh complete on commit as
select emp_id, count(*) cnt
from relatives
group by emp_id;

alter table emp_dep_mv
add constraint emp_dep_mv_chk
check (cnt <= 3)
deferrable;

However, this approach might not be performant in a large, busy production database, in which case you could go for an approach that uses triggers and a check constraint, plus an extra column on the employees table:

alter table employees add num_relatives number(1,0) default 0 not null;

-- Populate for existing data
update employees
set num_relatives = (select count(*) from relatives r
                     where r.emp_id = e.emp_id)
where exists (select * from relatives r
              where r.emp_id = e.emp_id);

alter table employees add constraint emp_relatives_chk
check (num_relatives <= 3);

create trigger relatives_trg
after insert or update or delete on relatives
for each row
begin
   if inserting or updating then
      update employees
      set    num_relatives = num_relatives + 1
      where  emp_id = :new.emp_id;
   end if;
   if deleting or updating then
      update employees
      set    num_relatives = num_relatives - 1
      where  emp_id = :old.emp_id;
   end if;
end;
Tony Andrews
  • 129,880
  • 21
  • 220
  • 259
  • I am not satisfied... my requirements need a simple constraint in the first go (during table creation)... An inside-out approach... I think it is not possible at row-level, or is it? – Pop Stack Jan 09 '12 at 03:51
  • You are correct: your requirements cannot be fulfilled. It is impossible to create just a simple constraint to enforce this rule. – Tony Andrews Jan 09 '12 at 10:53
  • The revised version of onedaywhen's answer should do the trick. – Tripartio Mar 24 '15 at 14:35
3

Add an new integer not null column occurrence, add a check constraint occurrence BETWEEN 1 AND 3, add a unique constraint on the compound of emp_id and occurrence, optionally add helper procs to maintain occurrence values.

onedaywhen
  • 55,269
  • 12
  • 100
  • 138