Um de seus números numéricos de 'época' parece ser muito grande (ou muito pequeno) para o
numtodsinterval()
função de manusear. O maior valor que você pode passar como número de segundos é 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.
Como uma época, o maior número permitido de segundos representa 2038-01-19 03:14:07. Este é o problema do ano de 2038 , essencialmente.
Você também pode chegar lá com um número negativo:
SQL> select numtodsinterval(-2208988800, 'SECOND') as interval from dual;
SQL Error: ORA-01873: the leading precision of the interval is too small
Usando
-power(2, 31)
quebra para um valor positivo, mas qualquer coisa menor que esses erros: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
Você está dividindo por 1000, então uma de suas colunas F a K tem um valor que excede 2147483647000. Isso deve ser bastante fácil de encontrar, e você pode considerar adicionar uma restrição de verificação a essas colunas para que elas não possam ser definidas também high - verifique se o valor da coluna é menor ou igual a
1000 * (power(2, 31) - 1)
. E maior que zero, ou maior que-1000 * (power(2, 31)
também. O motivo pelo qual não ocorre erro quando você tem um filtro como
where Col1 = 123
é que seu filtro (predicado) é enviado para a consulta de visualização e as linhas com valores muito altos não são avaliadas. Talvez você tenha apenas um único valor, e seu col1
o valor é não 123 e seu col2
o valor é não 'xyz'. Se você identificar uma linha com problema e filtrar usando seu col1
real valor ele ainda vai dar erro. Sem filtros, a avaliação é feita para todas as linhas. O número negativo específico que você tem parece ser um número mágico:
SQL> select date '1970-01-01' - 2208988800/86400 from dual;
DATE'1970-01-01'-2208988800/86400
---------------------------------
1900-01-01 00:00:00
Se você quiser excluir isso, deverá modificar a definição da visualização para adicionar um filtro, por exemplo:
...
AND tab2.colh > 0
ou altere a expressão da coluna para lidar com isso, ignorando-a e deixando-a nula, ou provavelmente retornando mais útil essa data mágica:
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,
Você também pode mudar de usar um intervalo para usar aritmética de data:
TO_CHAR(DATE'1970-01-01' + ( tab2.colh / 86400000 ), 'YYYY/MM/DD HH24:MI:SS') AS Col13,
Você terá que modificar a definição de visualização em vez de sua consulta, a menos que
colh
está incluído na lista de seleção (o que não parece ser), e mesmo que estivesse, você só poderia excluí-lo - e isso ainda pode nem sempre evitar o erro, dependendo de como o otimizador tratou a consulta.