Jedna z numerycznych liczb „epoki” wydaje się być za duża (lub za mała) dla numtodsinterval()
funkcja do obsługi. Największa wartość, jaką możesz przekazać jako liczba sekund, to 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.
Jako epokę najwyższa dozwolona liczba sekund reprezentuje 2038-01-19 03:14:07. To jest problem roku 2038 , zasadniczo.
Możesz się tam również dostać z liczbą ujemną:
SQL> select numtodsinterval(-2208988800, 'SECOND') as interval from dual;
SQL Error: ORA-01873: the leading precision of the interval is too small
Używanie -power(2, 31)
zawija do wartości dodatniej, ale wszystkie mniejsze błędy:
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
Dzielisz przez 1000, więc jedna z Twoich kolumn od F do K ma wartość przekraczającą 2147483647000. Powinno to być dość łatwe do znalezienia i warto rozważyć dodanie ograniczenia sprawdzającego do tych kolumn, aby nie można ich było również ustawić high - sprawdź, czy wartość kolumny jest mniejsza lub równa 1000 * (power(2, 31) - 1)
. I albo większe niż zero, albo większe niż-1000 * (power(2, 31)
też.
Powód, dla którego nie występuje błąd, gdy masz filtr taki jak where Col1 = 123
polega na tym, że filtr (predykat) jest wypychany do zapytania widoku, a wiersze ze zbyt wysokimi wartościami nie są oceniane. Być może masz tylko jedną taką wartość i jej col1
wartość to nie 123 i jego col2
wartość to nie „xyz”. Jeśli zidentyfikujesz wiersz problemu i przefiltrujesz przy użyciu jego rzeczywistego col1
wartość to nadal będzie błąd. Bez filtrów ocena jest wykonywana dla wszystkich wierszy.
Konkretna liczba ujemna, którą masz, wydaje się być liczbą magiczną:
SQL> select date '1970-01-01' - 2208988800/86400 from dual;
DATE'1970-01-01'-2208988800/86400
---------------------------------
1900-01-01 00:00:00
Jeśli chcesz to wykluczyć, zmodyfikuj definicję widoku, aby dodać filtr, np.:
...
AND tab2.colh > 0
lub zmień wyrażenie kolumny, aby to obsłużyć, albo ignorując i pozostawiając wartość pustą, albo prawdopodobnie bardziej użytecznie zwracając tę magiczną datę:
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,
Możesz również zmienić użycie przedziału na arytmetykę dat:
TO_CHAR(DATE'1970-01-01' + ( tab2.colh / 86400000 ), 'YYYY/MM/DD HH24:MI:SS') AS Col13,
Będziesz jednak musiał zmodyfikować definicję widoku, a nie zapytanie, chyba że colh
znajduje się na liście wyboru (na którą nie wydaje się być), a nawet gdyby tak było, można go tylko wykluczyć – a to i tak nie zawsze może uniknąć błędu, w zależności od tego, jak optymalizator obsługiwał zapytanie.