问题
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.
回答1:
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)
来源:https://stackoverflow.com/questions/12027207/how-to-create-sql-constraints-in-my-table