【问题标题】:PL/SQL trigger giving error?PL/SQL 触发器给出错误?
【发布时间】:2023-03-16 15:25:02
【问题描述】:

在考试中得到了这个问题,但触发器出错。请帮忙。

问题

客户(cust_id、cust_name、地址) 租金信息(cust_id,date_out,date_due_in,date_returned,罚款) 租用视频(cust_id,no_of_videos)

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

客户在同一日期内拍摄的视频不得超过 3 个。返回视频时,返回日期会更新。如果有罚款,就会计算出来。

罚款计算方式

  1. 延迟前三天卢比 每天 10 个

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

  3. 六日后收取罚款 每天 30 卢比

为执行更新操作编写一个过程/触发器。

我是这样解决的。

做了三个表:

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;

/

还书时更新 Fine 的触发器

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');

【问题讨论】:

    标签: database stored-procedures plsql triggers


    【解决方案1】:

    在行级触发器中,您只需对 :NEW 进行赋值即可更改列的值 - 您无需发出 UPDATE 语句。例如:

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

    【讨论】:

      【解决方案2】:

      为什么要使用触发器?通过开发这些过程,您正在构建一个非常清晰的 API,但随后您将代码放入触发器中。为什么不将此逻辑合并到return_proc 中以使事情更明显?

      【讨论】:

      • 这是一道考试题,题目是“A trigger is used to insert data into rent_info table”
      • 我想了解什么是触发器是件好事,但实际上应该谨慎使用它们。
      猜你喜欢
      • 2016-04-22
      • 2014-04-07
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      • 2011-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多