だから私はIDX_ATS_CALC_END_TIMEと呼ばれるインデックスを持つテーブルを持っています. 列はタイムスタンプ値です。この列には、別の列 (Interval_duration) が移入または更新されたときに列を自動的に移入するトリガーもあります。
トリガーは以下です。
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;
そして問題なく戻ってきました。
このエラーが発生せずにこの列を正常に更新できたのは、トリガーを無効にして更新を実行し、トリガーをもう一度有効にすることだけでした。これは私にとって実行可能な解決策ではありません。
したがって、誰かがこの種の問題に遭遇したことがあるかどうか、およびこのエラーを修正するために他にどのような手順を試みることができるかを知りたい.
更新: 以下に、関数 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;
これは私の前任者によって書かれましたが、基本的には、与えられた数値を回して間隔値に変換するだけです。
どんな助けや提案も大歓迎です。
ありがとうございました。