sql >> Base de Datos >  >> RDS >> Oracle

Oracle 2 guiones en la columna de números?

No significa nada, y no es 'para' nada; Tus datos están corruptos, me temo. El -- es un valor real de su tabla, pero no es un número. La representación interna de números de Oracle está cubierta en la nota 1031902.6 si tiene acceso a eso, o este lo explica si no lo hace . Si realmente fuera un número negativo, entonces el último byte hexadecimal debería ser 66. Volcar el número que parece ser, con un solo signo menos, no dos, lo cual no tiene sentido, da:

select dump(-1331013400000000000000000000, 1016) from dual;

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

Crear números no válidos en Oracle no es sencillo (supongo que no esperaría que lo fuera), pero este es un método que he usado antes. Una de las pistas, además del doble signo menos y de que todos tienen la misma longitud, es que convertir el valor descargado de nuevo en un número no da el mismo resultado:

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

Esto es de Oracle 9i, los cierres que tengo ahora a una base de datos 8i, por lo que los resultados pueden variar un poco.

No poder hacer to_number(value) es una gran pista también, por supuesto; hay un to_char() implícito cuando hace eso, intenta convertir la representación de texto en un número, lo que explica el error. El to_char() El valor tampoco coincide con lo que hace una simple selección, curiosamente. Vería el mismo error si hiciera eso con sus datos.

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

A menos que sepa de dónde provienen los datos incorrectos y aún tenga los originales, probablemente no pueda recuperar estos valores. Creo que lo mejor que puede hacer es ignorarlo o reemplazarlo con algo que migrará; si el campo es anulable, entonces null sería la opción segura, de lo contrario, supongo que tendrías que elegir un valor mágico.

La identificación y modificación de las filas afectadas se puede realizar a través de una función; posiblemente algo como:

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

Con el mismo valor inválido creado anteriormente y un valor válido:

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

No es ideal de ninguna manera, pero en este punto creo que solo estás salvando lo que puedes. Puede eliminar las filas en lugar de actualizarlas, o establecer el valor en otra cosa, depende de cómo desee proceder.

Podría intentar involucrar a Oracle para ver si pueden averiguar qué sucedió y ver si tienen algún truco para volver a los valores originales, lo que parece poco probable, pero no estoy seguro de que obtenga mucho apoyo para una versión tan antigua de la base de datos.

Por supuesto, sin saber cómo y cuándo se introdujo la corrupción (quizás a través de una importación dudosa, o a través de un programa OCI defectuoso), debe cuestionar la validez de todos los demás datos, tanto en esa columna como en otros lugares. En este caso, la corrupción parece muy uniforme:todos los valores no válidos parecen estar construidos de la misma manera, por lo que puede estar bien. Sin embargo, en general, algo que coloca bytes incorrectos en un valor interno podría generar un valor incorrecto, pero aún válido. Podría parecer correcto, o podría estar fuera del valor esperado original en órdenes de magnitud, y realmente no hay forma de saberlo.