Oracle
 sql >> Datenbank >  >> RDS >> Oracle

ORA-01873:die führende Präzision

Eine Ihrer numerischen Epochenzahlen scheint zu groß (oder zu klein) für numtodsinterval() zu sein Funktion zu handhaben. Der größte Wert, den Sie als Anzahl von Sekunden übergeben können, ist 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.

Als Epoche repräsentiert die höchste zulässige Anzahl von Sekunden 2038-01-19 03:14:07. Dies ist das Jahr-2038-Problem , im Wesentlichen.

Sie können auch mit einer negativen Zahl dorthin gelangen:

SQL> select numtodsinterval(-2208988800, 'SECOND') as interval from dual;

SQL Error: ORA-01873: the leading precision of the interval is too small

Verwenden von -power(2, 31) wird auf einen positiven Wert umgebrochen, aber alles niedrigere Fehler:

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

Sie dividieren durch 1000, also hat eine Ihrer Spalten F bis K einen Wert, der 2147483647000 überschreitet. Das sollte ziemlich einfach zu finden sein, und Sie sollten in Betracht ziehen, diesen Spalten eine Check-Einschränkung hinzuzufügen, damit sie nicht auch festgelegt werden können hoch - Prüfen Sie, ob der Spaltenwert kleiner oder gleich 1000 * (power(2, 31) - 1) ist . Und entweder größer als Null oder größer als 1000 * (power(2, 31)). auch.

Der Grund, warum es nicht fehlschlägt, wenn Sie einen Filter wie where Col1 = 123 haben ist, dass Ihr Filter (Prädikat) in die Ansichtsabfrage hochgeschoben wird und die Zeile(n) mit zu hohen Werten nicht ausgewertet werden. Vielleicht haben Sie nur einen einzigen solchen Wert, und zwar col1 Wert ist nicht 123 und dessen col2 Wert ist nicht 'xyz'. Wenn Sie eine problematische Zeile identifizieren und anhand ihres tatsächlichen col1 filtern Wert wird es immer noch Fehler. Ohne Filter erfolgt die Auswertung für alle Zeilen.

Die spezifische negative Zahl, die Sie haben, scheint eine magische Zahl zu sein:

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

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

Wenn Sie das ausschließen möchten, müssten Sie die Ansichtsdefinition ändern, um entweder einen Filter hinzuzufügen, z. B.:

...
AND tab2.colh > 0

oder ändern Sie den Spaltenausdruck, um ihn zu handhaben, indem Sie ihn entweder ignorieren und null lassen oder wahrscheinlich sinnvollererweise dieses magische Datum zurückgeben:

    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,

Sie könnten auch von der Verwendung eines Intervalls zur Verwendung der Datumsarithmetik wechseln:

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

Sie müssen jedoch eher die Ansichtsdefinition als Ihre Abfrage ändern, es sei denn, colh in der Auswahlliste enthalten ist (was anscheinend nicht der Fall ist), und selbst wenn es so wäre, könnten Sie es nur ausschließen - und das vermeidet den Fehler möglicherweise nicht immer, je nachdem, wie der Optimierer die Abfrage gehandhabt hat.