2012-06-12 51 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:インデックスキーが見つからない、obj#97523、ファイル4、ブロック244(2)

上記のインデックスは、機能ベースのインデックスです。索引で使用される関数は、calc_end_time列のsys_extract_utcです。

私はこの問題を解決しようと数日間過ごしました。インデックスを再構築しました。インデックスの削除と再作成を試みました。この2つはこの問題の一般的な答えと思われますが、私にとってはうまくいきませんでした。 私は、次を使用してインデックスに分析しました:

ANALYZE INDEX IDX_ATS_CALC_END_TIME VALIDATE STRUCTURE;

をし、それが問題なく帰ってきました。

このエラーを表示せずにこの列を正常に更新することができたのは、トリガーを無効にして更新を実行し、再度トリガーを有効にすることだけでした。これは私にとって実行可能な解決策ではありません。

誰かがこの種の問題に遭遇したことを知りたいと思っています。このエラーを修正するために他にどのような手順をとることができますか?

UPDATE:これは私の前任者によって書かれましたが、基本的にはそれがないすべてが与えられた数値を回しているとに変換

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; 

:あなた以下 は、関数pb_util.secondtointerval()のコードを見つけますインターバル値。

ご意見やご提案は大変ありがとうございます。

ありがとうございます。

+0

関数を簡単にすることができます: 'return seconds_in *(interval '1' second);'? –

+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の関数ベースのインデックスのためのGoogle。それはあなたを助けるでしょう。 – Luftwaffe

+0

私はcalc_end_timeに固定値を割り当てようとしましたが、それでも同じora-エラーで戻ってきました。また、インデックスが関数ベースのインデックスであることがわかったと同時に、それが何をしているのかを確認し、実行しているすべてが列のsys_extract_utcです。 – James213

3

は、以下のことを試してみてください。

SELECT * 
    FROM ALL_OBJECTS 
    WHERE OBJECT_ID = 97523 

これはあなたにOracleがで問題を抱えているオブジェクトを教えてくれます。おそらくそれはあなたが疑うインデックスですが、そうでないかもしれません。

共有して楽しんでください。

+0

これは実際に私が上記のエラーでタグ付けされたインデックスを見つけるために行ったことですが、他人には知ってもらいやすいでしょう。ありがとう – James213

関連する問題