2012-06-12 38 views
5

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.

+0

¿Puede simplificar la función para: 'return seconds_in * (intervalo '1' second);'? –

+0

¿Cuál es la definición para su índice 'IDX_ATS_CALC_END_TIME'? ¿Es un índice basado en función? –

+0

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. –

Respuesta

3

Creo que está sucediendo porque su desencadenador tiene una función no determinista -> pb_util.secondtointerval. Realmente no sé lo que este método realmente hace. Intenta asignar un valor estático en lugar de CALC_END_TIME y comprueba si funciona tu disparador.

para apoyar esta Voy a poner un pequeño trozo de código aquí:

SQL> CREATE TABLE t (a INTEGER) 
Table created. 

SQL> CREATE OR REPLACE FUNCTION f (a INTEGER) 
    RETURN INTEGER "DETERMINISTIC" 
AS 
    cnt INTEGER; 
BEGIN 
    RETURN ROUND ("DBMS_RANDOM.VALUE (1, 100)"); 
END f; 
Function created. 

SQL> CREATE INDEX t_idx ON t (f(a)) COMPUTE STATISTICS 
Index created. 

SQL> INSERT INTO t 
    SELECT ROWNUM 
    FROM user_objects 
5 rows created. 

SQL> DELETE FROM t 
DELETE FROM t 
Error at line 28 
ORA-08102: index key not found, obj# 48928, file 4, block 36 (2) 

espero que ayude !!

+0

He actualizado mi pregunta para incluir el código para la función pb_util.secondtointerval. – James213

+0

@ James213 ¿Intentó asignar algún valor de corrección a CALC_END_TIME en lugar de recuperar el valor de la función? Le diría si el uso de una función no determinista es la causa raíz del problema. Por ej. modifique FUNCTION SecondToInterval para que devuelva 1 y compruebe si existe algún problema. También google para índices basados ​​en funciones en Oracle. Esto te ayudará. – Luftwaffe

+0

Intenté asignar un valor fijo a calc_end_time y todavía regresó con el mismo error de ora. Además, tan pronto como me di cuenta de que el índice era un índice basado en funciones, verifiqué qué estaba haciendo y todo lo que se está ejecutando es un sys_extract_utc en la columna – James213

3

intente lo siguiente:

SELECT * 
    FROM ALL_OBJECTS 
    WHERE OBJECT_ID = 97523 

Esto le dirá el objeto de Oracle está teniendo problemas con. Lo más probable es que sea el índice que sospeche, pero quizás no.

Comparte y disfruta.

+0

Esto es en realidad lo que hice para encontrar el índice etiquetado en el error mencionado anteriormente, pero sería bueno que otros lo supieran. Gracias – James213

Cuestiones relacionadas