Tengo una tabla con un índice llamado IDX_ATS_CALC_END_TIME. La columna es un valor de marca de tiempo. Esta columna también tiene un activador que rellena automáticamente la columna cuando se completa o actualiza otra columna (Interval_duration).Razones para obtener (ORA-8102 "clave de índice no encontrada")
El disparador es a continuación:
TRIGGER "DATAMART"."TRG_ATS_CALC_END_TIME"
BEFORE INSERT OR UPDATE OF INTERVAL_DURATION ON DATAMART.AGG_TIME_SUMMARY
FOR EACH ROW
DECLARE
BEGIN
IF :New.INTERVAL_DURATION > 0 THEN
:New.calc_end_time := :New.start_date_time + pb_util.secondtointerval(:New.INTERVAL_DURATION);
ELSE
:NEW.CALC_END_TIME := :New.start_date_time;
END IF;
EXCEPTION
WHEN OTHERS THEN
pb_util.logdata(1, 'TRG_ATS_CALC_END_TIME', 'Exception Thrown in interval: ' || :New.Interval_DURATION, SQLERRM || ' stack: ' || dbms_utility.format_error_backtrace);
END TRG_ATS_CALC_END_TIME;
Cuando mi mesa es inicialmente poblada no hay problemas. Mi problema es que cuando voy a realizar una inserción/actualización sobre la mesa y tratar de modificar esta columna, ya sea cambiando directamente la columna o simplemente actualizar la columna interval_duration tengo este error que se produce:
ORA-08102: clave de índice no encontrada, obj # 97523, archivo 4, bloque 244 (2)
El índice mencionado es un índice basado en funciones. La función que se utiliza en el índice es sys_extract_utc en la columna calc_end_time.
He pasado varios días tratando de resolver este problema. Reconstruí el índice, intenté eliminar y volver a crear el índice. Estos dos parecen ser la respuesta común para este problema, pero no funcionaron para mí. He analizado el índice utilizando la siguiente:
ANALYZE INDEX IDX_ATS_CALC_END_TIME VALIDATE STRUCTURE;
y me lo han devuelto sin problemas.
La única vez que he podido actualizar correctamente esta columna sin obtener este error fue deshabilitando el desencadenador, realizando la actualización y habilitando el desencadenante nuevamente. Esta no es una solución viable para mí.
Así que me gustaría saber si alguien alguna vez ha encontrado este tipo de problema y qué otros pasos puedo intentar corregir este error.
ACTUALIZACIÓN: A continuación encontrará la función pb_util.secondtointerval() Código:
FUNCTION SecondToInterval
(Seconds_IN NUMBER
)
RETURN CONST.PBInterval
IS
sec NUMBER(20, 9);
days NUMBER;
hours NUMBER;
minutes NUMBER;
seconds NUMBER(20, 9);
IntervalAsText NVARCHAR2(32);
ReturnInterval INTERVAL DAY(9) TO SECOND(9);
begin
sec := NVL(Seconds_IN, 0);
days := trunc(sec/(24*60*60));
sec := sec - days*24*60*60;
hours := trunc(sec/(60*60));
sec := sec - hours*60*60;
minutes := trunc(sec/60);
sec := sec - minutes*60;
seconds := trunc(sec);
sec := sec - seconds;
sec := trunc(1000000000*sec);
IntervalAsText := cast(days as nvarchar2)
|| ' ' || cast(hours as nvarchar2)
|| ':' || substr('00' || cast(minutes as nvarchar2), -2, 2)
|| ':' || substr('00' || cast(seconds as nvarchar2), -2, 2)
|| '.' || substr('000000000' || cast(sec as nvarchar2), -9, 9);
--dbms_output.put_line(intervalastext);
ReturnInterval := TO_DSInterval(IntervalAsText);
--ReturnInterval := TO_DSInterval('999999999 23:59:59.999999999');
--dbms_output.put_line(ReturnInterval);
RETURN ReturnInterval;
EXCEPTION
WHEN OTHERS THEN
pb_util.logdata(1, 'PB_UTIL.SecondToInterval', 'ERROR(99A): ', intervalastext);
dbms_output.put_line(intervalastext);
RAISE;
end SecondToInterval;
esto fue escrito por mi predecesor, pero básicamente lo único que hace es convertir el valor numérico dado y lo convierte en un valor de intervalo.
Cualquier ayuda o sugerencia es muy apreciada.
Gracias.
¿Puede simplificar la función para: 'return seconds_in * (intervalo '1' second);'? –
¿Cuál es la definición para su índice 'IDX_ATS_CALC_END_TIME'? ¿Es un índice basado en función? –
http://docs.oracle.com/cd/E11882_01/server.112/e17766/e7500.htm#sthref2691 sugiere que esto podría ser un error. Aunque la respuesta de Saurabh indica que puede ocurrir con un índice basado en funciones basado en una función no determinista. –