如何编写一个触发器,为成员未付余额帐户添加2美元的延迟罚款

时间:2014-12-01 20:32:37

标签: sql database oracle triggers oracle10g

我想创建一个触发器,强制延迟返回罚款是每天2美元。罚款应自动计算并添加到余额中。下面是我的代码以及我对触发器的尝试。触发器只占一天的租赁代码,但如果我能找出其中一个租赁代码,另外两个很容易弄明白。

到目前为止,我有什么触发器代码:

Create or Replace Trigger Late_Rule
BEFORE INSERT ON Transaction
For each Row
DECLARE
NofDays NUMBER; 
ChargeDays Number;
Fee Number;

BEGIN

SELECT count(Rental_Code) into NofDays
From Transaction Group by Mem_num having  Mem_num= :new.Mem_num;
 DBMS_output.put_line(NofDays);

If Rental_Code = 'R101'
 If (Date_Rented_Out - Date_returned) > 1
    NofDays- 1 = ChargeDays
    ChargeDays * 2 = Fee
ELSE 
Fee = 0
  END IF;
END IF;

Update Fee into Unpaid_Bal

end;
/


  show error;

--Attempt 2

Create or replace trigger Late_Fee_Rule
Before UPDATE ON transaction
for each row
DECLARE
Fine_Due NUMBER;
BEGIN
SET Fine_Due = trunc(sysdate - date_rented_out) * 2
where date_returned is null
and (sysdate - date_rented_out) > decode (Rental_code, 'R101', 1, 'R103', 3, 'R105', 5);
Update Member
where Unpaid_Bal = (Unpaid_Bal + Fine_Due)


End;
/
show error;

2 个答案:

答案 0 :(得分:0)

你最近问过几个关于触发器的问题,所以我认为你正在了解它们。但是,您已达到触发器不适合您需要实现的业务逻辑的程度。

  1. 这样的嵌入式查询不能很好地扩展。
  2. 在多会话环境中,逻辑可能会产生错误的结果。
  3. 从业务角度来看,罚款被添加到错误的交易中。
  4. 同样从商业角度来看,在错误的会员租借另一部电影之前,没有可见的罚款。
  5. 这样的触发器使维护更加困难,因为它们隐藏了人们不期望它们的业务规则。
  6. 你很难写出触发器,这表明你走错了路。更好的解决方案是使用数据库作业每天检查一次所有未退回的电影,并计算每笔交易的罚款。看起来你打算在TRANSACTION表上有一个很好的到期列:这是一种方法。生活稍微困难一些,因为租期是一个字符串代码而不是天数,而且你不会存储截止日期。

    update transaction
    set fine_due = trunc(sysdate - date_returned_out) * 2
    where date_returned is null
    and (sysdate - date_returned_out) > decode (rental_code, 'R101', 1, 'R103', 3, 'R105', 5)
    /
    

答案 1 :(得分:0)

如果任何数据(如罚款到期)会持续变化(例如每天),则根本不要将其存储在模型中。

相反,使用视图在报告时计算它,例如(改编自APC的例子):

CREATE transaction_vw AS
SELECT t.*
      ,CASE WHEN date_returned is null
             and (sysdate - date_returned_out)
               > DECODE(rental_code
                       ,'R101', 1
                       ,'R103', 3
                       ,'R105', 5)
       THEN trunc(sysdate - date_returned_out) * 2
       END AS fine_due
FROM transaction t;