1

i have this table:

id | product_group_id | percentage
1  | 1                | 0.2
2  | 1                | 0.3
3  | 1                | 0.5
4  | 2                | 0.4
5  | 2                | 0.6

I want to know if there is a way to create constraints that for each product_group_id the percentage will be equal to 1 ( if product_group_id = 1 so 0.2 + 0.3 + 0.5 = 1).
For example if i will change the percentage where id = 2 to 0.8 or 0.1, the update (or insert) will fail because the sum is not 1.

Thanks in advanced.

5
  • 1
    And what if a product has 1/3? This number will be rounded when represented in percent, making it impossible to achieve 1. Commented Aug 19, 2012 at 14:30
  • @Andre What do you mean? Commented Aug 19, 2012 at 14:32
  • @Ofer that you will have to deal with rounding errors. Commented Aug 19, 2012 at 14:49
  • what database are you using? Create a trigger associated with this table to check the constraint. Commented Aug 19, 2012 at 15:03
  • How would you add the first row in a group? Commented Aug 19, 2012 at 17:16

1 Answer 1

4

It would generally make more sense to enforce this sort of constraint in the API you build on top of the table to manipulate the percentages. Assuming, of course, that each product_group_id will be manipulated by at most one session at a time.

If you do really want to enforce this sort of restriction, you could create a materialized view that refreshes on commit and create a constraint on that materialized view. Something like

SQL> create table table_name(
  2    id number primary key,
  3    product_group_id number,
  4    percentage number
  5  );

Table created.

SQL> create materialized view log on table_name;

Materialized view log created.

SQL> ed
Wrote file afiedt.buf

  1  create materialized view mv_table_name
  2    refresh on commit
  3  as
  4  select product_group_id, sum(percentage) total_percentage
  5    from table_name
  6*  group by product_group_id
SQL> /

Materialized view created.

SQL> alter table mv_table_name
  2    add( constraint sum_of_1 check( total_percentage = 1 ));

Table altered.

That will allow you to insert rows that sum to 1

SQL> insert into table_name values( 1, 1, 0.5 );

1 row created.

SQL> insert into table_name values( 2, 1, 0.5 );

1 row created.

SQL> commit;

Commit complete.

and will throw an error when you try to commit changes that cause the sum to be something other than 1

SQL> insert into table_name values( 3, 1, 0.1 );

1 row created.

SQL> commit;
commit
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-02290: check constraint (SCOTT.SUM_OF_1) violated

Note that this is checked at commit time which is what you really need since you'll need to violate the constraint during a transaction when you want to insert multiple rows.

And, as has been pointed out, if there is the possibility of rounding errors, you probably want the CHECK constraint to allow sums that are 1 +/- some small epsilon (i.e between 0.999999 and 1.000001)

Sign up to request clarification or add additional context in comments.

Comments

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.