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

Oracle 2 bindestreger i talkolonnen?

Det betyder ikke noget, og det er ikke 'for' noget; dine data er korrupte, er jeg bange for. -- er en faktisk værdi fra din tabel, men det er ikke et tal. Oracles interne repræsentation for tal er dækket af note 1031902.6, hvis du har adgang til det, eller dette forklarer det, hvis du ikke gør det . Hvis det virkelig var et negativt tal, skulle den sidste hexadecimale byte være 66. Dumping af det tal, det ser ud til at være - med et enkelt minustegn, ikke to, hvilket er meningsløst - giver:

select dump(-1331013400000000000000000000, 1016) from dual;

DUMP(-1331013400000000000000000000,1016)
----------------------------------------
Typ=2 Len=6: 31,58,46,64,43,66           

At oprette ugyldige tal i Oracle er ikke ligetil (jeg formoder, at du ikke ville forvente det), men dette er en metode, jeg har brugt før. Et af sporene, bortset fra det dobbelte minustegnet og at de alle er lige lange, er, at konvertering af den dumpede værdi tilbage til et tal ikke giver det samme resultat:

create table t42(value number);

declare
  n number;
begin
  dbms_stats.convert_raw_value('32ea004366', n);
  insert into t42 (value) values (n);
end;
/

select value from t42;

                                 VALUE
--------------------------------------
           -<3:13400000000000000000000

Dette er fra Oracle 9i, de lukker jeg har nu til en 8i database, så resultaterne kan variere lidt.

Ikke at kunne gøre to_number(value) er selvfølgelig også et stort fingerpeg; der er en implicit to_char() når du gør det, så prøver den at konvertere tekstgengivelsen til et tal, hvilket forklarer fejlen. to_char() værdi matcher heller ikke, hvad et simpelt udvalg gør, interessant nok. Du vil se den samme fejl, hvis du gjorde det med dine data.

select to_number(value) from t42;
select to_number(value) from t42
                 *
ERROR at line 1:
ORA-01722: invalid number

select to_char(value) from t42;

TO_CHAR(VALUE)
----------------------------------------
-`003400000000000000000000

Medmindre du ved, hvor de dårlige data kom fra og har originalen stadig, kan du sandsynligvis ikke redde disse værdier. Jeg tror, ​​det bedste du kan gøre er at ignorere det eller erstatte det med noget, der vil migrere - hvis feltet er nullbart, så null ville være den sikre mulighed, ellers tror jeg, du bliver nødt til at vælge en magisk værdi.

Identifikation og ændring af de berørte rækker kan gøres via en funktion; muligvis noget som:

create or replace function null_bad_number(value number)
return number deterministic as
  tmp_value number;
  invalid_number exception;
  pragma exception_init(invalid_number, -1722);
begin
  select to_number(value) into tmp_value from dual;
  return value;
exception
  when invalid_number then
    return null;
end;
/

Med den samme ugyldige værdi oprettet tidligere og én gyldig værdi:

insert into t42 (value) values (0.9574875526618150);

select * from t42;

     VALUE
----------
-`.003E+24
.957487553

update t42 set value = null
where value is not null
and null_bad_number(value) is null;

1 row updated.

select * from t42;

     VALUE
----------

.957487553

Ikke ideelt på nogen måde, men på dette tidspunkt tror jeg, at du bare redder, hvad du kan. Du kan slette rækkerne i stedet for at opdatere dem, eller indstille værdien til noget andet, det afhænger af, hvordan du vil fortsætte.

Du kan prøve at få Oracle involveret for at se, om de kan finde ud af, hvad der skete, og se, om de har nogle tricks til at komme tilbage til de oprindelige værdier - hvilket virker usandsynligt - men jeg er ikke sikker på, at du ville få meget støtte til sådan en gammel version af databasen.

Uden at vide, hvordan og hvornår korruptionen blev introduceret (via en risikable import måske, eller via et buggy OCI-program), skal du naturligvis stille spørgsmålstegn ved gyldigheden af ​​alle de andre data, både i den kolonne og andre steder. I dette tilfælde ser korruptionen meget ensartet ud - alle de ugyldige værdier ser ud til at være konstrueret på samme måde - så du kan være okay. Generelt kan noget, der sætter forkerte bytes ind i en intern værdi, få en forkert, men stadig gyldig værdi. Det kan se rigtigt ud, eller det kan være størrelsesordener ud fra den oprindelige forventede værdi, og der er virkelig ingen måde at sige det.




  1. Vælg den seneste række med GROUP BY i MySQL

  2. pivottabel i mysql

  3. CEIL() Funktion i Oracle

  4. Automatiser versionsnummer-hentning fra .Dtsx-filer