To nic nie znaczy i nie jest „za” nic; Twoje dane są uszkodzone, obawiam się. --
jest rzeczywistą wartością z Twojej tabeli, ale nie jest liczbą. Wewnętrzna reprezentacja firmy Oracle dotycząca liczb została omówiona w nocie 1031902.6, jeśli masz do niej dostęp, lub wyjaśnia to, jeśli nie
. Jeśli rzeczywiście była to liczba ujemna, to ostatni bajt szesnastkowy powinien wynosić 66. Zrzucenie liczby, którą wydaje się być - z pojedynczym znakiem minusa, a nie dwoma, co jest bez znaczenia - daje:
select dump(-1331013400000000000000000000, 1016) from dual;
DUMP(-1331013400000000000000000000,1016)
----------------------------------------
Typ=2 Len=6: 31,58,46,64,43,66
Tworzenie nieprawidłowych liczb w Oracle nie jest proste (przypuszczam, że nie spodziewałbyś się, że tak będzie), ale jest to metoda, z której korzystałem wcześniej. Jedną ze wskazówek, oprócz podwójnego znaku minus i tego, że wszystkie mają tę samą długość, jest to, że przekształcenie zrzuconej wartości z powrotem na liczbę nie daje tego samego wyniku:
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
To jest z Oracle 9i, zamknięcia, które mam teraz, do bazy danych 8i, więc wyniki mogą się nieco różnić.
Brak możliwości wykonania to_number(value)
jest oczywiście dużą wskazówką; istnieje niejawna to_char()
kiedy to robisz, próbuje przekonwertować reprezentację tekstową na liczbę, co wyjaśnia błąd. to_char()
Co ciekawe, wartość nie pasuje do tego, co robi prosty wybór. Zobaczysz ten sam błąd, jeśli zrobisz to ze swoimi danymi.
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
O ile nie wiesz, skąd pochodzą złe dane i nadal masz oryginał, prawdopodobnie nie możesz uratować tych wartości. Myślę, że najlepsze, co możesz zrobić, to zignorować go lub zastąpić czymś, co będzie podlegać migracji - jeśli pole jest dopuszczalne, to null
byłaby bezpieczną opcją, w przeciwnym razie musiałbyś wybrać magiczną wartość.
Identyfikowanie i modyfikowanie dotkniętych wierszy można wykonać za pomocą funkcji; prawdopodobnie coś takiego:
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;
/
Z tą samą nieprawidłową wartością utworzoną wcześniej i jedną prawidłową wartością:
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
W żadnym wypadku nie jest to idealne rozwiązanie, ale w tym momencie myślę, że po prostu ratujesz to, co możesz. Możesz usunąć wiersze zamiast aktualizować je lub ustawić wartość na coś innego, zależy to od tego, jak chcesz kontynuować.
Możesz spróbować zaangażować Oracle, aby sprawdzić, czy mogą dowiedzieć się, co się stało i sprawdzić, czy mają jakieś sztuczki, aby wrócić do pierwotnych wartości – co wydaje się mało prawdopodobne – ale nie jestem pewien, czy uzyskasz duże wsparcie dla taka stara wersja bazy danych.
Oczywiście, nie wiedząc, jak i kiedy wprowadzono uszkodzenie (być może przez podejrzany import lub przez błędny program OCI), musisz zakwestionować poprawność wszystkich innych danych, zarówno w tej kolumnie, jak iw innych miejscach. W tym przypadku uszkodzenie wygląda bardzo jednolicie — wszystkie nieprawidłowe wartości wydają się być skonstruowane w ten sam sposób — więc możesz być w porządku. Ogólnie rzecz biorąc, coś, co umieszcza nieprawidłowe bajty w wartości wewnętrznej, może być błędną, ale nadal poprawną wartością. Może wyglądać dobrze lub może to być rzędy wielkości od pierwotnej oczekiwanej wartości i naprawdę nie ma sposobu, aby to stwierdzić.