PL / SQL触发器给出错误?

时间:2011-04-08 04:36:53

标签: database stored-procedures plsql triggers

对于考试有这个问题但是从触发器中获得错误。请帮忙。

问题

客户(的cust_id,CUST_NAME,地址) rent_info(的cust_id,date_out,date_due_in,date_returned,细) rented_video(的cust_id,no_of_videos)

发行日期应为当前日期,截止日期应为发布日期后7天。当客户返回视频时,rent_info表应包含cust_id,date_out,date_due_in。触发器用于将数据插入到rent_info表中。在插入数据之前必须进行以下验证。

客户不得在同一天拍摄超过3个视频。返回视频时,更新返回日期。并计算罚款。

罚款由

计算
  1. 延迟的前三天Rs 每天10个

  2. 接下来的三天 延迟每天20卢比

  3. 六个日期之后罚款 每天30卢比

  4. 编写用于执行更新操作的过程/触发器。

    我这样解决了。

    制作三张桌子:

    create table customer(
    
    cust_id number(4),
    
    cust_name varchar2(8),
    
    address varchar2(8)
    
    );
    
    
    
    create table rent_info(
    
    cust_id number(4),
    
    date_out date,
    
    date_due_in date,
    
    date_returned date,
    
    fine number(10)
    
    );
    
    
    
    create table rented_video(
    
    cust_id number(4),
    
    no_vid number(4)
    
    );
    

    拿书的程序

    create or replace procedure take_proc(c_id in int,d_out in date) is
    
    val number(3) :=0;
    
    begin
    
        insert into rent_info values(c_id,d_out,d_out+7,NULL,0);
    
        update rented_video set no_vid=no_vid+1 where cust_id=c_id;
    
        --val := select count(date_out) from rent_info where (date_out='12-jan-2010');
    
        --dbms_output.put_line('Values is '||val);
    
    end;
    
    /
    

    退回书籍的程序

    create or replace procedure return_proc(c_id in int,d_ret in date) is
    
    val number(3) :=0;
    
    begin
    
        update rented_video set no_vid=no_vid-1 where cust_id=c_id;
    
        update rent_info set date_returned=d_ret where cust_id=c_id;
    
        --insert into rent_info values(c_id,d_out,d_out+7,NULL,0);
    
        update rented_video set no_vid=no_vid-1 where cust_id=c_id;
    
        --val := select count(date_out) from rent_info where (date_out='12-jan-2010');
    
        --dbms_output.put_line('Values is '||val);
    
    end;
    
    /
    

    在退回图书时触发更新

    create or replace trigger ret_trig
    
    before update on rent_info
    
    for each row
    
    declare
    
    tfine number(7) := 0;
    
    temp number(7) := 0;
    
    rdate date;
    
    dudate date;
    
    cid number(4);
    
    begin
    
        --select date_returned into rdate from rent_info;
    
        --select date_due_in into dudate from rent_info;
    
        --select cust_id into cid from rent_info;
    
        --if (rdate- dudate) <=3 then
    
            --temp := rdate- dudate;
    
            --tfine := tfine+ temp * 10;
    
        --end if;
    
        if (:new.date_returned-:old.date_due_in ) <=3 then
    
            temp := :new.date_returned-:old.date_due_in;
    
            tfine := tfine+ temp * 10;
    
            dbms_output.put_line('Fine Values is '|| tfine);
    
        elsif (:new.date_returned-:old.date_due_in ) <=6 then
    
            temp := :new.date_returned-:old.date_due_in;
    
            tfine := tfine+ 3 * 10;
    
            tfine := tfine+ 20*(temp-3);
    
            dbms_output.put_line('Fine Values is '|| tfine);
    
        else
    
            temp := :new.date_returned-:old.date_due_in;
    
            tfine := tfine+ 3 * 10;
    
            tfine := tfine+ 3 * 20;
    
            tfine := tfine+ 30*(temp-6);
    
            dbms_output.put_line('Fine Values is '|| tfine);
    
        end if; 
    
    
    
        --update rent_info set fine=fine+tfine where cust_id=:old.cust_id;
    
    end;
    
    /
    

    我可以正确计算罚款,但无法将其更新到rent_info表(触发器的最后一行进行了更新评论)。

    我认为我在触发器创建方面犯了一些逻辑错误。请告诉我如何正确解决问题。

    要插入的示例值

    insert into customer values(1,'john','abc h');
    
    insert into customer values(2,'joseph','cde h');
    
    insert into rented_video values(1,0);
    
    insert into rented_video values(2,0);
    
    exec take_proc(1,'12-jan-2010');
    
    exec take_proc(2,'13-jan-2010');
    
    exec return_proc(1,'16-jan-2010');
    exec return_proc(2,'29-jan-2010');
    

2 个答案:

答案 0 :(得分:3)

在行级触发器中,只需执行以下操作即可更改列的值:NEW - 您不发出UPDATE语句。 e.g:

:NEW.fine := :OLD.fine + tfine;

答案 1 :(得分:0)

为什么使用触发器?您正在通过开发这些过程来构建一个非常清晰的API,然后将代码推送到触发器中。为什么不将这个逻辑纳入return_proc以使事情变得更加明显?