数値の「エポック」番号の1つが、numtodsinterval()
に対して大きすぎる(または小さすぎる)ようです 処理する関数。秒数として渡すことができる最大値は2^31-1です:
SQL> select numtodsinterval(power(2,31) - 1, 'SECOND') as interval from dual;
INTERVAL
--------------
24855 3:14:7.0
SQL> select numtodsinterval(power(2,31), 'SECOND') as interval from dual;
SQL Error: ORA-01873: the leading precision of the interval is too small
01873. 00000 - "the leading precision of the interval is too small"
*Cause: The leading precision of the interval is too small to store the
specified interval.
*Action: Increase the leading precision of the interval or specify an
interval with a smaller leading precision.
エポックとして、最大許容秒数は2038-01-1903:14:07を表します。 これは、2038年問題です 、本質的に。
負の数でもそこにたどり着くことができます:
SQL> select numtodsinterval(-2208988800, 'SECOND') as interval from dual;
SQL Error: ORA-01873: the leading precision of the interval is too small
-power(2, 31)
の使用 正の値に折り返されますが、そのエラーよりも低い値は次のとおりです。
SQL> select numtodsinterval(power(2,31) - 1, 'SECOND') as interval from dual;
INTERVAL
--------------
24855 3:14:7.0
SQL> select numtodsinterval(-power(2,31), 'SECOND') as interval from dual;
INTERVAL
--------------
24855 3:14:8.0
SQL> select numtodsinterval(-power(2,31) - 1, 'SECOND') as interval from dual;
SQL Error: ORA-01873: the leading precision of the interval is too small
1000で除算しているため、列FからKの1つに2147483647000を超える値があります。これはかなり簡単に見つけることができます。これらの列にもチェック制約を追加して、設定できないようにすることを検討してください。 high-列の値が1000 * (power(2, 31) - 1)
以下であることを確認します 。そして、ゼロより大きいか、-1000 * (power(2, 31)
where Col1 = 123
のようなフィルターがある場合にエラーが発生しない理由 フィルタ(述語)がビュークエリにプッシュアップされ、値が高すぎる行は評価されないということです。おそらく、そのような値は1つだけで、そのcol1
値はではありません 123とそのcol2
値はではありません 'xyz'。問題のある行を特定し、実際のcol1
を使用してフィルタリングする場合 値はまだエラーになります。フィルタがない場合、評価はすべての行に対して行われます。
あなたが持っている特定の負の数は魔法の数のようです:
SQL> select date '1970-01-01' - 2208988800/86400 from dual;
DATE'1970-01-01'-2208988800/86400
---------------------------------
1900-01-01 00:00:00
それを除外したい場合は、ビュー定義を変更して、フィルターを追加する必要があります(例:
)。...
AND tab2.colh > 0
または、列式を変更して処理するか、厳密に調整してnullのままにするか、おそらくより便利にその魔法の日付を返します。
TO_CHAR(CASE WHEN tab2.colh = -2208988800000 THEN DATE'1900-01-01'
ELSE DATE'1970-01-01' + NUMTODSINTERVAL( tab2.colh / 1000,'SECOND')
END, 'YYYY/MM/DD HH24:MI:SS') AS Col13,
間隔の使用から日付演算の使用に変更することもできます:
TO_CHAR(DATE'1970-01-01' + ( tab2.colh / 86400000 ), 'YYYY/MM/DD HH24:MI:SS') AS Col13,
ただし、colh
でない限り、クエリではなくビュー定義を変更する必要があります。 は選択リストに含まれていますが(そうではないようです)、除外することしかできませんでした。オプティマイザーがクエリを処理した方法によっては、エラーを常に回避できるとは限りません。