ORA-01873:领先的精度 [英] ORA-01873: the leading precision

查看:332
本文介绍了ORA-01873:领先的精度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试查询视图,但收到ORA-01873:间隔的前导精度太小"错误消息.以下是查询.

I am trying to query view but getting "ORA-01873: the leading precision of the interval is too small" error message. Below is the query.

Select * from table order by Col1.

以下是视图结构:

Col1    NOT NULL NUMBER
Col2    NOT NULL NVARCHAR2(80)
Col3    NOT NULL NUMBER
Col4    NOT NULL VARCHAR2(10)
Col5        NVARCHAR2(80)
Col6        NVARCHAR2(255)
Col7        NUMBER
Col8    NOT NULL NVARCHAR2(255)
Col9    NOT NULL NVARCHAR2(1)
Col10   NOT NULL NUMBER
Col11       VARCHAR2(19)
Col12       VARCHAR2(19)
Col13       VARCHAR2(19)
Col14       VARCHAR2(19)
Col15       VARCHAR2(19)
Col16       VARCHAR2(19)
Col17       NUMBER
Col18       NVARCHAR2(255)
Col19       NVARCHAR2(80)
Col20   NOT NULL NUMBER

以下是视图定义:

SELECT tab2.cola AS Col1,
    tab1.col AS COl2,    
    tab2.colb AS Col3,
    tab7.col AS Col4,
    DECODE(tab3.col, NULL, tab4.col) AS COl5,
    tab8.col AS Col6,
    tab6.col AS COl7,
    tab2.Colc AS Col8,
    tab2.cold AS Col9,
    tab2.cole AS Col10,
    TO_CHAR(TO_DATE('1970/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS') + NUMTODSINTERVAL( tab2.colf / 1000,'SECOND'), 'YYYY/MM/DD HH24:MI:SS') AS COl11,
    TO_CHAR(TO_DATE('1970/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS') + NUMTODSINTERVAL( tab2.colg / 1000,'SECOND'), 'YYYY/MM/DD HH24:MI:SS') AS Col12,
    TO_CHAR(TO_DATE('1970/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS') + NUMTODSINTERVAL( tab2.colh / 1000,'SECOND'), 'YYYY/MM/DD HH24:MI:SS') AS Col13,
    TO_CHAR(TO_DATE('1970/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS') + NUMTODSINTERVAL( tab2.coli / 1000,'SECOND'), 'YYYY/MM/DD HH24:MI:SS') AS Col14,
    TO_CHAR(TO_DATE('1970/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS') + NUMTODSINTERVAL( tab2.colj / 1000,'SECOND'), 'YYYY/MM/DD HH24:MI:SS') AS COl15,
    TO_CHAR(TO_DATE('1970/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS') + NUMTODSINTERVAL( tab2.colk / 1000,'SECOND'), 'YYYY/MM/DD HH24:MI:SS') AS COl16,
    tab2.coll AS Col17,
    tab9.col AS Col18,
    tab10.col AS Col19,
    tab2.colm AS Col20
FROM tab1 ,
    tab2 ,
    tab3,
    tab4,
    tab5,
    tab6,
    tab7,
    tab8,
    tab9,
    tab10
WHERE ....

其他查询运行良好,如 select * from table where Col1 = 123select * from table where Col2 = 'xyz' order by Col1 但上面的查询不是为任何上校工作.请提出建议.

Other queries are running fine like select * from table where Col1 = 123 or select * from table where Col2 = 'xyz' order by Col1 but above query is not working for any col. Please suggest.

推荐答案

对于 numtodsinterval() 函数而言,您的一个数字纪元"数字似乎太大(或太小).您可以传递的最大秒数为 2^31-1:

One of your numeric 'epoch' numbers appears to be too large (or too small) for the numtodsinterval() function to handle. The biggest value you can pass as the number of seconds is 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 年的问题.

As an epoch that highest allowed number of second represents 2038-01-19 03:14:07. This is the year 2038 problem, essentially.

你也可以用负数到达那里:

You can get there with a negative number too:

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) 包装为正值,但任何低于该值的错误:

Using -power(2, 31) wraps to a positive value, but anything lower than that errors:

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).

You are dividing by 1000, so one of your columns F to K has a value that exceeds 2147483647000. That should be fairly easy to find, and you might want to consider adding a check constraint to those columns so they can't be set too high - check that the column value is less than or equal to 1000 * (power(2, 31) - 1). And either greater than zero, or greater than-1000 * (power(2, 31) too.

当你有一个像 where Col1 = 123 这样的过滤器时它不会出错的原因是你的过滤器(谓词)被推入视图查询和具有值的行太高不评价.也许你只有一个这样的值,它的 col1 值是 not 123 而它的 col2 值是 not'xy'.如果您识别出问题行并使用它的实际 col1 值进行过滤,它仍然会出错.在没有过滤器的情况下,对所有行进行评估.

The reason it doesn't error when you have a filter like where Col1 = 123 is that your filter (predicate) is pushed up into the view query and the row(s) with values that are too high are not evaluated. Perhaps you only have a single such value, and its col1 value is not 123 and its col2 value is not 'xyz'. If you identify a problem row and filter using it's actual col1 value it will still error. With no filters the evaluation is done for all rows.

您所拥有的特定负数似乎是一个神奇的数字:

The specific negative number you have seems to be a magic number:

SQL> select date '1970-01-01' - 2208988800/86400 from dual;

DATE'1970-01-01'-2208988800/86400
---------------------------------
1900-01-01 00:00:00              

如果您想排除它,那么您将修改视图定义以添加过滤器,例如:

If you want to exclude that then you would have modify the view definition to either add a filter, e.g:

...
AND tab2.colh > 0

或更改列表达式以处理它,要么忽略它并将其保留为空,或者可能更有用地返回那个神奇的日期:

or change the column expression to handle it, eithe rignoring it and leaving it null, or probably more usefully returning that magic date:

    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,

您也可以从使用间隔更改为使用日期算法:

You could also change from using an interval to using date arithmetic:

    TO_CHAR(DATE'1970-01-01' + ( tab2.colh / 86400000 ), 'YYYY/MM/DD HH24:MI:SS') AS Col13,

你必须修改视图定义而不是你的查询,除非 colh 包含在选择列表中(它似乎不是),即使是你只能排除它 - 这仍然可能无法始终避免错误,具体取决于优化器如何处理查询.

You'll have to modify the view definition rather than your query though, unless colh is included in the select list (which it doesn't seem to be), and even if it was you could only exclude it - and that still might not always avoid the error, depending on how the optimiser handled the query.

这篇关于ORA-01873:领先的精度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆