sql >> Database teknologi >  >> RDS >> Oracle

ORA-01873:den førende præcision

Et af dine numeriske 'epoke'-tal ser ud til at være for stort (eller for lille) til numtodsinterval() funktion at håndtere. Den største værdi, du kan sende, da antallet af sekunder er 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.
 

Som en epoke repræsenterer det højest tilladte antal sekunder 2038-01-19 03:14:07. Dette er 2038-problemet i det væsentlige.

Du kan også komme dertil med et negativt tal:

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

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

Brug af -power(2, 31) ombrydes til en positiv værdi, men alt lavere end det fejler:

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
 

Du dividerer med 1000, så en af ​​dine kolonner F til K har en værdi, der overstiger 2147483647000. Det burde være ret nemt at finde, og du vil måske overveje at tilføje en kontrolbegrænsning til disse kolonner, så de ikke også kan indstilles høj - kontroller, at kolonneværdien er mindre end eller lig med 1000 * (power(2, 31) - 1) . Og enten større end nul eller større end-1000 * (power(2, 31) også.

Grunden til at det ikke fejler, når du har et filter som where Col1 = 123 er, at dit filter (prædikat) er skubbet op i view-forespørgslen, og rækken/rækkerne med værdier, der er for høje, bliver ikke evalueret. Måske har du kun en enkelt sådan værdi, og dens col1 værdien er ikke 123 og dens col2 værdien er ikke 'xyz'. Hvis du identificerer en problemrække og filter ved hjælp af dens faktiske col1 værdi det vil stadig fejle. Uden filtre udføres evalueringen for alle rækker.

Det specifikke negative tal, du har, ser ud til at være et magisk tal:

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

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

Hvis du vil udelukke det, skal du ændre visningsdefinitionen til enten at tilføje et filter, f.eks.:

...
AND tab2.colh > 0
 

eller skift kolonneudtrykket for at håndtere det, enten ved at rignorere det og lade det være nul, eller sandsynligvis mere nyttigt returnere den magiske dato:

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,

Du kan også skifte fra at bruge et interval til at bruge dato-aritmetik:

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

Du bliver dog nødt til at ændre visningsdefinitionen i stedet for din forespørgsel, medmindre colh er inkluderet i udvælgelseslisten (hvilket det ikke ser ud til at være), og selvom det var, kunne du kun udelukke det - og det kan stadig ikke altid undgå fejlen, afhængigt af hvordan optimeringsværktøjet håndterede forespørgslen.




  1. Flere stigende rækkefølge virker ikke i Mysql

  2. automatisere en SQL-forespørgsel til at køre hver måned

  3. MySQL Connector ODBC odbc.ini 'Option' flag værdier

  4. Yii2:Hvordan skriver man en særskilt SQL-forespørgsel?