Едно от вашите числови числа за „епоха“ изглежда твърде голямо (или твърде малко) за 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-19 03: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 има стойност, която надвишава 2147483647000. Това трябва да е доста лесно за намиране и може да помислите за добавяне на ограничение за проверка към тези колони, така че и те да не могат да бъдат зададени високо - проверете дали стойността на колоната е по-малка или равна на 1000 * (power(2, 31) - 1)
. И или по-голямо от нула, или по-голямо от-1000 * (power(2, 31)
също.
Причината да не дава грешка, когато имате филтър като where Col1 = 123
е, че вашият филтър (предикат) се избутва нагоре в заявката за изглед и редовете с твърде високи стойности не се оценяват. Може би имате само една такава стойност и нейната 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
или променете израза на колоната, за да се справите с него, или като го игнорирате и го оставите нула, или вероятно по-полезно да върнете тази магическа дата:
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
е включено в списъка за избор (което изглежда не е) и дори да беше, можете само да го изключите - и това пак може да не избегне винаги грешката, в зависимост от това как оптимизаторът е обработил заявката.