Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I have a constraint on count of distinct values in a column in SQL?

Table: Relatives

  • emp_id
  • dep_id(composite primary key)

We have to restrict one employee to three dependents.

like image 237
pop stack Avatar asked Jan 07 '12 14:01

pop stack


People also ask

How do I count distinct values in a column in SQL?

The COUNT DISTINCT function returns the number of unique values in the column or expression, as the following example shows. SELECT COUNT (DISTINCT item_num) FROM items; If the COUNT DISTINCT function encounters NULL values, it ignores them unless every value in the specified column is NULL.

Can we use count with distinct in SQL?

Yes, you can use COUNT() and DISTINCT together to display the count of only distinct rows. SELECT COUNT(DISTINCT yourColumnName) AS anyVariableName FROM yourTableName; To understand the above syntax, let us create a table. Display all records from the table using select statement.

Which constraint allows a column to count by itself?

A check constraint is a type of integrity constraint in SQL which specifies a requirement that must be met by each row in a database table. The constraint must be a predicate. It can refer to a single column, or multiple columns of the table.


1 Answers

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;
like image 143
Tony Andrews Avatar answered Nov 04 '22 13:11

Tony Andrews