Nic to neznamená a není to „pro“ nic; vaše data jsou poškozená, obávám se. --
je skutečná hodnota z vaší tabulky, ale není to číslo. Interní reprezentace čísel společnosti Oracle je uvedena v poznámce 1031902.6, pokud k tomu máte přístup, nebo toto vysvětluje, pokud ne
. Pokud to bylo skutečně záporné číslo, pak by poslední hexadecimální bajt měl být 66. Vypsáním čísla, které se zdá být - s jediným znaménkem mínus, nikoli dvěma, což je nesmyslné - získá:
select dump(-1331013400000000000000000000, 1016) from dual;
DUMP(-1331013400000000000000000000,1016)
----------------------------------------
Typ=2 Len=6: 31,58,46,64,43,66
Vytváření neplatných čísel v Oracle není jednoduché (předpokládám, že byste to nečekali), ale toto je metoda, kterou jsem dříve používal. Jedním z vodítek, kromě dvojitého znaménka mínus a toho, že jsou všechny stejně dlouhé, je, že převedení dumpingové hodnoty zpět na číslo nedává stejný výsledek:
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
Toto je z Oracle 9i, zavření mám nyní k databázi 8i, takže výsledky se mohou trochu lišit.
Neschopnost udělat to_number(value)
je samozřejmě také velkým vodítkem; je tam implicitní to_char()
když to uděláte, tak se to pokouší převést reprezentaci textu na číslo, což vysvětluje chybu. to_char()
hodnota také neodpovídá tomu, co dělá jednoduchý výběr, je zajímavé. Pokud byste to udělali se svými daty, zobrazila by se stejná chyba.
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
Pokud nevíte, odkud se vzala špatná data a nemáte stále původní, pravděpodobně tyto hodnoty nezachráníte. Myslím, že nejlepší, co můžete udělat, je ignorovat ho nebo ho nahradit něčím, co bude migrovat – pokud je pole s možnou hodnotou null, pak null
by byla bezpečná možnost, jinak si myslím, že byste museli vybrat magickou hodnotu.
Identifikaci a úpravu dotčených řádků lze provést pomocí funkce; možná něco jako:
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;
/
Se stejnou dříve vytvořenou neplatnou hodnotou a jednou platnou hodnotou:
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
V žádném případě to není ideální, ale v tuto chvíli si myslím, že zachraňujete, co se dá. Řádky můžete raději smazat, než je aktualizovat, nebo nastavit hodnotu na něco jiného, záleží, jak chcete pokračovat.
Můžete zkusit zapojit Oracle, abyste zjistili, zda dokážou přijít na to, co se stalo, a zjistit, zda mají nějaké triky, jak se vrátit k původním hodnotám – což se zdá nepravděpodobné – ale nejsem si jistý, že byste získali velkou podporu pro taková stará verze databáze.
Samozřejmě, aniž byste věděli, jak a kdy byla korupce zavedena (možná pomocí riskantního importu nebo pomocí chybného OCI programu), musíte zpochybnit platnost všech ostatních dat, jak v tomto sloupci, tak jinde. V tomto případě vypadá poškození velmi jednotně - všechny neplatné hodnoty se zdají být konstruovány stejným způsobem - takže můžete být v pořádku. Obecně však platí, že něco, co vkládá nesprávné bajty do vnitřní hodnoty, může způsobit nesprávnou, ale stále platnou hodnotu. Mohlo by to vypadat dobře, nebo by to mohlo být řádově mimo původní očekávanou hodnotu, a opravdu to není jak poznat.