2012-06-12 25 views
5

因此,我有一個名爲IDX_ATS_CALC_END_TIME的索引表。該列是時間戳值。此列還具有一個觸發器,可在填充或更新另一個列(Interval_duration)時自動填充列。獲取原因(ORA-8102「索引鍵未找到」)

觸發低於:

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; 

當我的表是最初填充不存在任何問題。我的問題是,當我去在表上執行插入/更新並嘗試通過直接更改列或僅更新interval_duration列來修改此列時,我將此錯誤拋出:

ORA-08102: index key not found,obj#97523,file 4,block 244(2)

所提到的索引是基於函數的索引。在索引上使用的函數是calc_end_time列上的sys_extract_utc。

我花了好幾天試圖解決這個問題。我已經重建了索引,我嘗試刪除並重新創建索引。這兩個似乎是這個問題的常見答案,但它們並不適合我。 我使用下面的分析指標:

ANALYZE INDEX IDX_ATS_CALC_END_TIME VALIDATE STRUCTURE;

和它回來了,沒有任何問題。

我唯一能夠成功更新此列而不會出現此錯誤的時間是禁用觸發器,執行更新,然後再次啓用觸發器。這對我來說不是一個可行的解決方案。

所以我想知道是否有人遇到這種類型的問題,以及我可以嘗試修復這個錯誤的其他步驟。

UPDATE: 下面你會發現功能pb_util.secondtointerval()代碼:

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; 

這是寫的我的前任,但基本上它的作用是把給定的數字值,並將其轉換成間隔值。

任何幫助或建議,非常感謝。

謝謝。

+0

可以簡化的功能:'回報seconds_in *(間隔 '1' 秒);'? –

+0

您的索引'IDX_ATS_CALC_END_TIME'的定義是什麼?這是一個基於函數的索引嗎? –

+0

http://docs.oracle.com/cd/E11882_01/server.112/e17766/e7500.htm#sthref2691表明,這可能是一個錯誤。雖然Saurabh的答案表明它可以基於基於非確定性函數的基於函數的索引發生。 –

回答

3

我認爲這是因爲你的觸發器有一個非確定性函數 - > pb_util.secondtointerval。我真的不知道這種方法真的做什麼。嘗試將一些靜態值分配給CALC_END_TIME並檢查您的觸發器是否有效。

爲了支持這個,我將一小段代碼在這裏:

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) 

希望它可以幫助!

+0

我已更新我的問題以包含pb_util.secondtointerval函數的代碼。 – James213

+0

@ James213您是否嘗試將一些固定值分配給CALC_END_TIME,而不是從函數中獲取值?它會告訴你,使用非確定性函數是否是問題的根本原因。例如。修改FUNCTION SecondToInterval,使其返回1並檢查是否存在問題。谷歌的基於功能的索引在oracle中。它會幫助你。 – Luftwaffe

+0

我試着給calc_end_time分配一個固定值,它仍然返回相同的錯誤。此外,一旦我意識到指數我查了基於功能的索引它是什麼做的,所有正在運行在柱上 – James213

3

嘗試以下操作:

SELECT * 
    FROM ALL_OBJECTS 
    WHERE OBJECT_ID = 97523 

這會告訴你,甲骨文是有問題的對象。很可能這是您懷疑的索引,但可能不是。

分享和享受。

+0

這實際上是我在上面提到的錯誤中找到標記的索引,但是對於其他人來說,這很好。謝謝 – James213

相關問題