Trigger to calculate hours pl / sql

1

Good morning everyone and thanks in advance for the time you gave me;

My problem is the following one I have to program a trigger in my database that calculates the excess of hours or in its defect the hours of less and skips a warning.

I've put this;

create or replace trigger horas
before insert or update
on viajes
declare
exceso_horas exception;
menos_horas exception;
HORAS NUMBER(2);
MINUTOS NUMBER(2);
TOTALMINUTOS NUMBER (4,2);
TOTAL NUMBER (4,2);
idt PARTES.TRABAJADORES_ID%type;
est partes.estado%type;
BEGIN
SELECT TRABAJADORES_ID , extract(hour from (to_timestamp((select max(horafinal) from viajes where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO')), 'HH24:MI') - to_timestamp((select min(horainicial)from viajes where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO')),  'HH24:MI'))) ,
   extract(minute from (to_timestamp((select max(horafinal) from VIAJES where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO')), 'HH24:MI') - to_timestamp((select min(HORAINICIAL)from viajes where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO') ),  'HH24:MI'))) INTO  idt, HORAS, MINUTOS
FROM VIAJES where TRABAJADORES_ID =(select trabajadores_id from partes where estado='ABIERTO') group by TRABAJADORES_ID ;
TOTALMINUTOS:=MINUTOS/100;
TOTAL:=HORAS+TOTALMINUTOS;
IF TOTAL<8 THEN
RAISE menos_horas;
else 
RAISE exceso_horas;
end if;
EXCEPTION
when menos_horas then
 RAISE_APPLICATION_ERROR(-20001,'pocas horas');
when exceso_horas then
 RAISE_APPLICATION_ERROR(-20001,'muchas horas');
END horas;

and the consequences are this:

insert into viajes (id, horainicial, horafinal, trabajadores_id, fecha_id, albaran) values (25, '12:00','19:00',1,'10/05/2017',15)
Informe de error -
Error SQL: ORA-01427: single-row subquery returns more than one row
ORA-06512: at "LOGISTICA.HORAS", line 11
ORA-04088: error during execution of trigger 'LOGISTICA.HORAS'
01427. 00000 -  "single-row subquery returns more than one row"
*Cause:    
*Action:

I've also tried it with after

insert into viajes (id, horainicial, horafinal, trabajadores_id, fecha_id, albaran) values (25, '12:00','19:00',1,'10/05/2017',15)
Informe de error -
Error SQL: ORA-04091: table LOGISTICA.VIAJES is mutating, trigger/function may not see it
ORA-06512: at "LOGISTICA.HORAS", line 11
ORA-04088: error during execution of trigger 'LOGISTICA.HORAS'
04091. 00000 -  "table %s.%s is mutating, trigger/function may not see it"
*Cause:    A trigger (or a user defined plsql function that is referenced in
       this statement) attempted to look at (or modify) a table that was
       in the middle of being modified by the statement which fired it.
*Action:   Rewrite the trigger (or function) so it does not read that table.

a greeting.

    
asked by Bruno de Castro 10.05.2017 в 15:41
source

1 answer

0

It seems to me that you are mixing the errors and their respective causes. Here is an explanation of the 3 errors you mentioned and their causes.

single-row subquery returns more than one row

Error SQL: ORA-01427: single-row subquery returns more than one row
ORA-06512: at "LOGISTICA.HORAS", line 11
ORA-04088: error during execution of trigger 'LOGISTICA.HORAS'
01427. 00000 -  "single-row subquery returns more than one row"

If the details of your question are correct, the error should then come from the following query:

SELECT TRABAJADORES_ID,
       extract(hour from (to_timestamp((select max(horafinal) from viajes where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO')), 'HH24:MI') 
               - to_timestamp((select min(horainicial)from viajes where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO')),  'HH24:MI'))),
       extract(minute from (to_timestamp((select max(horafinal) from VIAJES where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO')), 'HH24:MI')
               - to_timestamp((select min(HORAINICIAL)from viajes where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO') ),  'HH24:MI')))
INTO  idt, HORAS, MINUTOS
FROM VIAJES 
where TRABAJADORES_ID = (select trabajadores_id from partes where estado='ABIERTO') 
group by TRABAJADORES_ID ;

In this case, the most likely cause is that your query is returning more than one record, which is not compatible with the syntax SELECT ... INTO ... .

ORA-04091: table LOGISTICA.VIAJES is mutating, trigger / function may not see it

Error SQL: ORA-04091: table LOGISTICA.VIAJES is mutating, trigger/function may not see it
ORA-06512: at "LOGISTICA.HORAS", line 11
ORA-04088: error during execution of trigger 'LOGISTICA.HORAS'
04091. 00000 -  "table %s.%s is mutating, trigger/function may not see it"
*Cause:    A trigger (or a user defined plsql function that is referenced in
       this statement) attempted to look at (or modify) a table that was
       in the middle of being modified by the statement which fired it.
*Action:   Rewrite the trigger (or function) so it does not read that table.

According to the question, you got this error by changing the trigger from BEFORE to AFTER . I am convinced that this is not true.

The error mutating trigger is due to the fact that in the trigger you are trying to read records of the table that are in the process of being modified by the statement insert or update . This is illegal in Oracle.

This type of error can happen if your trigger is a row level ( for each row ) trigger ( before or after , does not matter), or if it is a before < em> statement level trigger. Although it is not what you mentioned in your question, but I am sure that this error happens when your trigger has it as a before trigger.

One way to avoid this problem and that should work with the design of your trigger, is to modify the trigger so that, instead of firing before the modification , which would rather shoot after .

Changing ( before ):

create or replace trigger horas
before insert or update
on viajes

... a ( after ):

create or replace trigger horas
after insert or update
on viajes

SQL Error: ORA-20001: few hours

In the comments you mentioned that you also received the following error:

Informe de error - 
Error SQL: ORA-20001: pocas horas 
ORA-06512: at "LOGISTICA.HORAS", line 23 
ORA-04088: error during execution of trigger 'LOGISTICA.HORAS'

If this is the case, then it means that your trigger worked correctly. This error is because the trigger correctly executed your code where you specified that if TOTAL<8 then you want to throw the error RAISE_APPLICATION_ERROR(-20001,'pocas horas');

With that said, obviously your logic needs to be revised, because with the following lines:

IF TOTAL<8 THEN
RAISE menos_horas;
else 
RAISE exceso_horas;
end if;

... you are guaranteeing that, regardless of the value of TOTAL , you will always throw an error, so your INSERT or UPDATE will never succeed.

    
answered by 10.05.2017 в 17:12