ank*_*dey 2 sql oracle oracle11g
我试图查询视图,但得到" ORA-01873:间隔的领先精度太小 "错误消息.以下是查询.
Select * from table order by Col1.
Run Code Online (Sandbox Code Playgroud)
以下是视图结构:
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
Run Code Online (Sandbox Code Playgroud)
以下是视图定义:
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 ....
Run Code Online (Sandbox Code Playgroud)
其他查询运行正常select * from table where Col1 = 123,select * from table where Col2 = 'xyz' order by Col1但上面的查询不适用于任何col.请建议.
您的一个数字'epoch'数字似乎太大(或太小),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.
Run Code Online (Sandbox Code Playgroud)
作为最高允许秒数的时代表示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
Run Code Online (Sandbox Code Playgroud)
使用-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
Run Code Online (Sandbox Code Playgroud)
您除以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
Run Code Online (Sandbox Code Playgroud)
如果要排除它,那么您可以修改视图定义以添加过滤器,例如:
...
AND tab2.colh > 0
Run Code Online (Sandbox Code Playgroud)
或者更改列表达式来处理它,通过对它进行rignoring并将其保留为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,
Run Code Online (Sandbox Code Playgroud)
您还可以使用间隔更改为使用日期算法:
TO_CHAR(DATE'1970-01-01' + ( tab2.colh / 86400000 ), 'YYYY/MM/DD HH24:MI:SS') AS Col13,
Run Code Online (Sandbox Code Playgroud)
你必须修改视图定义而不是你的查询,除非colh它包含在选择列表中(它似乎不是),即使它只是你可以排除它 - 而且仍然可能并不总是避免错误,具体取决于优化器处理查询的方式.
| 归档时间: |
|
| 查看次数: |
10710 次 |
| 最近记录: |