1

私はこのテーブルを持っています:

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

product_group_idごとにパーセンテージが1に等しくなる制約を作成する方法があるかどうかを知りたいです(product_group_id = 1の場合、0.2 + 0.3 + 0.5 = 1)。
たとえば、id = 2のパーセンテージを0.8または0.1に変更すると、合計が1でないため、更新(または挿入)は失敗します。

よろしくお願いします。

4

1 に答える 1

4

一般に、パーセンテージを操作するためにテーブルの上に構築するAPIでこの種の制約を適用する方が理にかなっています。もちろん、それぞれproduct_group_idが一度に最大1つのセッションによって操作されると仮定します。

この種の制限を本当に適用したい場合は、コミット時に更新されるマテリアライズド・ビューを作成し、そのマテリアライズド・ビューに制約を作成することができます。何かのようなもの

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.

これにより、合計が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.

合計が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

複数の行を挿入する場合はトランザクション中に制約に違反する必要があるため、これはコミット時にチェックされることに注意してください。

また、指摘されているように、丸め誤差の可能性がある場合は、CHECK1 +/-いくつかの小さなイプシロン(つまり、0.999999〜1.000001)の合計を許可するように制約が必要になる可能性があります。

于 2012-08-19T17:35:36.730 に答える