只是想知道是否可以创建一个触发器来每月检查指定的约束。
例如。
桌租
|ID|会员|图书|
----------------------
1 | 约翰 |童话|
2 | 约翰 |摩擦|
3 | 约翰 |漫画|
4 | 约翰 |杂志|
限制:会员每月只能借4本书。
我想过使用 count(book) <= 4 但不知道如何实施每月基础约束。
有什么建议吗?
只是想知道是否可以创建一个触发器来每月检查指定的约束。
例如。
桌租
|ID|会员|图书|
----------------------
1 | 约翰 |童话|
2 | 约翰 |摩擦|
3 | 约翰 |漫画|
4 | 约翰 |杂志|
限制:会员每月只能借4本书。
我想过使用 count(book) <= 4 但不知道如何实施每月基础约束。
有什么建议吗?
如果表只存储实际数据,那么它很简单:
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;
/
但是如果表也存储历史数据,那么您需要一些时间戳列,ferent_date。因此计数查询应更改为以下内容:
select count(*) into v_count
from rent where member = :new.member
and rent_date > add_months(sysdate, -1);
在某些情况下,读取当前正在修改的表可能会导致“变异表错误”,但上面的触发器是安全的。
使用触发器,虽然它似乎有效,但这样做是一种危险的方式,因为并行运行的会话不会看到正在进行的会话中插入的数据。你可以通过一个实体化的视图来做到这一点:
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