Oracle
 sql >> база данни >  >> RDS >> Oracle

Oracle 2 тирета в числовата колона?

Това не означава нищо и не е „за“ нищо; страхувам се, че вашите данни са повредени. -- е действителна стойност от вашата таблица, но не е число. Вътрешното представяне на Oracle за числа е описано в бележка 1031902.6, ако имате достъп до нея, или това го обяснява, ако не го правите . Ако наистина беше отрицателно число, тогава последният шестнадесетичен байт трябва да е 66. Изхвърлянето на числото, което изглежда е - с един знак минус, а не с два, което е безсмислено - дава:

select dump(-1331013400000000000000000000, 1016) from dual;

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

Създаването на невалидни числа в Oracle не е лесно (предполагам, че не бихте очаквали да бъде), но това е метод, който съм използвал преди. Една от уликите, освен двойния знак минус и че всички са с еднаква дължина, е, че преобразуването на изхвърлената стойност обратно в число не дава същия резултат:

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

Това е от Oracle 9i, затварянията, които имам сега, към база данни 8i, така че резултатите може да варират малко.

Не можете да направите to_number(value) също е голяма улика, разбира се; има имплицитно to_char() когато правите това, той се опитва да преобразува текстовото представяне в число, което обяснява грешката. to_char() стойността не съвпада с това, което прави обикновен избор, което е интересно. Ще видите същата грешка, ако сте направили това с вашите данни.

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

Освен ако не знаете откъде идват лошите данни и имате оригиналния дестилатор, вероятно не можете да спасите тези стойности. Мисля, че най-доброто, което можете да направите, е да го игнорирате или да го замените с нещо, което ще мигрира - ако полето е nullable, тогава null би било безопасният вариант, в противен случай предполагам, че ще трябва да изберете магическа стойност.

Идентифицирането и модифицирането на засегнатите редове може да се извърши чрез функция; вероятно нещо като:

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;
/

Със същата невалидна стойност, създадена по-рано, и една валидна стойност:

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

Не е идеален в никакъв случай, но в този момент мисля, че просто спасявате каквото можете. Можете да изтриете редовете, вместо да ги актуализирате, или да зададете стойността на нещо друго, зависи как искате да продължите.

Можете да опитате да включите Oracle, за да видите дали могат да разберат какво се е случило и дали имат някакви трикове, за да се върнат към първоначалните стойности - което изглежда малко вероятно - но не съм сигурен, че ще получите много подкрепа за такава стара версия на базата данни.

Разбира се, без да знаете как и кога е въведена корупцията (може би чрез неправилно импортиране или чрез бъгава OCI програма), трябва да поставите под въпрос валидността на всички други данни, както в тази колона, така и другаде. В този случай корупцията изглежда много еднаква - всички невалидни стойности изглежда са конструирани по един и същи начин - така че може да сте добре. Като цяло обаче нещо, което поставя неправилни байтове във вътрешна стойност, може да доведе до грешна, но все още валидна стойност. Може да изглежда почти правилно или може да е на порядък от първоначалната очаквана стойност и наистина няма начин да се каже.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Тип на Java за дата/час, когато използвате Oracle Date с Hibernate

  2. Oracle оптимизира OR + IN до OR + EXISTS, което е много бавно

  3. Пролетна партида:Не може да се увеличи самоличността; вложеното изключение е com.microsoft.sqlserver.jdbc.SQLServerException:Невалидно име на обект „BATCH_JOB_SEQ“?

  4. Индекс с постоянно време за колона с низове в база данни на Oracle

  5. Как да вмъкна файл в базата данни на Oracle?