Триггер PL / SQL дает ошибку? - PullRequest
0 голосов
/ 08 апреля 2011

Получил этот вопрос на экзамене, но получил ошибку от триггера. Пожалуйста помоги.

Вопрос

клиент (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. За первые три дня задержки РТС 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');

Ответы [ 2 ]

3 голосов
/ 08 апреля 2011

Внутри триггера уровня строки вы изменяете значение столбца, просто выполняя присваивание: NEW - вы не выполняете инструкцию UPDATE.например:

:NEW.fine := :OLD.fine + tfine;
0 голосов
/ 09 апреля 2011

Почему вы используете триггер? Вы разрабатываете очень понятный API, разрабатывая эти процедуры, но затем вставляете код в триггер. Почему бы не включить эту логику в return_proc, чтобы сделать вещи более очевидными?

...