sql >> Databasteknik >  >> RDS >> Oracle

TO_char returnerar ett snedstreck värde efter att ha konverterat ett tal till String

Det verkar som om du har skadad data i tabellen. Vilket leder till några frågor, inklusive hur kom det dit, och vad kan du göra åt det?

Korrupt numeriskt (eller datum )-värden kommer ofta från OCI-program, men det finns några felrapporter som föreslår imp har varit känt för att orsaka korruption. Den interna representationen finns dokumenterad i supportnota 1007641.6, men jag hittar något i stil med denna förklaring lättare att arbeta med när du återskapar problem, och att använda ett PL/SQL-block är möjligt istället för ett OCI-program.

De två siffrorna du har problem med bör representeras internt så här:

select dump(0.000000000099, 16) as d1,
    dump(0.000000001680, 16) as d2
from dual;

D1                 D2
------------------ ---------------------
Typ=2 Len=2: bb,64 Typ=2 Len=3: bc,11,51

Jag har inte räknat ut exakt vilka värden du har i din tabell, men jag kan visa ett liknande resultat:

create table t42 (amount number(32,12)) nologging;

declare
    n number;
begin
    dbms_stats.convert_raw_value('bb65', n);
    insert into t42 (amount) values (n);
    dbms_stats.convert_raw_value('bc100000', n);
    insert into t42 (amount) values (n);
end;
/

Att dumpa värdena visar att de ser lite udda ut:

column d1 format a25
column d2 format a25
select amount, dump(amount) d1, dump(amount, 16) d2
from t42;

                     AMOUNT D1                        D2                      
--------------------------- ------------------------- -------------------------
              0.00000000010 Typ=2 Len=2: 187,101      Typ=2 Len=2: bb,65        
             0.000000001499 Typ=2 Len=3: 188,16,0     Typ=2 Len=3: bc,10,0      

Att köra din formatering mot det ger liknande resultat:

select amount as actual__________amount,
    TO_CHAR(amount,'FM99999999999999999999999999999990.099999999999')
        as amount__________Changed
from t42
order by amount;    

     ACTUAL__________AMOUNT AMOUNT__________CHANGED                      
--------------------------- ----------------------------------------------
              0.00000000010 ############################################## 
             0.000000001499 0.00000000150/

Om du kan lägga till dump() utdata för din egen data till frågan så kan jag se om jag kan återskapa exakt de värden du ser.

Anekdotiskt kan det vara möjligt att "korrigera" detta genom att uppdatera data, t.ex.:

update t42 set amount = amount * 1;

select amount, dump(amount) d1, dump(amount, 16) d2
from t42;

                     AMOUNT D1                        D2                      
--------------------------- ------------------------- -------------------------
               0.0000000001 Typ=2 Len=2: 188,2        Typ=2 Len=2: bc,2         
             0.000000001499 Typ=2 Len=3: 188,15,100   Typ=2 Len=3: bc,f,64

select amount as actual__________amount,
    TO_CHAR(amount,'FM99999999999999999999999999999990.099999999999')
        as amount__________Changed
from t42
order by amount;

     ACTUAL__________AMOUNT AMOUNT__________CHANGED                      
--------------------------- ----------------------------------------------
               0.0000000001 0.0000000001                                   
             0.000000001499 0.000000001499                                 

Du måste dock fråga vad det faktiska korrekta värdet är, vilket troligen kommer tillbaka till hur/varför/när det korrumperades. Jag skulle vara mycket försiktig med att röra dessa uppgifter om de överhuvudtaget är viktiga, och skulle verkligen måste följa @DazzaL:s råd för att få Oracle Support involverad för att reda ut det.




  1. Justera Postgresql-prestanda och minnesanvändning i ett python-arbetsflöde

  2. SQL Server Databas Replikering

  3. Hur väljer jag ett fast antal rader för varje grupp?

  4. MySQL-fråga för flera tabeller