Oracle触发每月检查约束

时间:2012-11-12 18:29:36

标签: oracle count constraints

只是想知道是否可以创建一个触发器来按月检查指定约束。

例如。
餐桌租 | ID |会员|预订|
----------------------
1 |约翰|童话|

2 |约翰|摩擦|

3 |约翰|漫画|

4 |约翰|杂志|

约束:会员每月只允许借4本书。

我想过使用count(book)< = 4但不知道如何实现月度基础约束。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

如果表只存储实际数据,则非常简单:

create or replace trigger tr_rent
before insert on rent
for each row 
declare
  v_count number;
begin
  select count(*) into v_count
  from rent where member = :new.member;

  if v_count >= 4 then
    raise_application_error(-20001, 'Limit reached');
  end if;
end;
/

但是如果表存储历史数据,那么你需要一些时间戳列,f.e。 rent_date。因此,count-query应更改为以下内容:

select count(*) into v_count
from rent where member = :new.member
and rent_date > add_months(sysdate, -1);

在某些情况下,读取当前正在修改的表可能会导致“变更表错误”,但上面的触发器是安全的。

答案 1 :(得分:1)

使用触发器,虽然它似乎有效,但这是一种危险的方式,因为并行运行的会话不会看到来自inprogress会话的插入数据。 你可以通过材料化的观点来做到这一点:

SQL> create table rent (id number primary key, member varchar2(30), book varchar2(20), date_rented date);

Table created.

SQL> create index rent_ix1 on rent ( member, date_rented);

Index created.

SQL> create materialized view log on rent with rowid(member,date_rented)
  2  including new values;

Materialized view log created.

SQL> create materialized view rent_month_check
  2  refresh fast on commit
  3  as
  4  select trunc(date_rented, 'mm') month, member, count(*) rentals
  5    from rent
  6   group by trunc(date_rented, 'mm'), member;

Materialized view created.

SQL> alter table rent_month_check
  2  add constraint rent_month_check_ck1 check (rentals <= 4);

Table altered.

SQL> insert into rent values(1, 'DazzaL', 'crime', sysdate);

1 row created.

SQL> commit;

Commit complete.

SQL> insert into rent values(2, 'DazzaL', 'mystery', sysdate+1);

1 row created.

SQL> commit;

Commit complete.

SQL> insert into rent values(3, 'DazzaL', 'fantasy', sysdate+2);

1 row created.

SQL> commit;

Commit complete.

SQL> insert into rent values(4, 'DazzaL', 'politics', sysdate+3);

1 row created.

SQL> commit;

Commit complete.

SQL> insert into rent values(5, 'DazzaL', 'thriller', sysdate+4);

1 row created.

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


SQL> select * from rent_month_check;

MONTH     MEMBER                            RENTALS
--------- ------------------------------ ----------
01-NOV-12 DazzaL                                  4