Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle 2 hífens na coluna de número?


Não significa nada, e não é 'para' nada; seus dados estão corrompidos, receio. O -- é um valor real da sua tabela, mas não é um número. A representação interna da Oracle para números é abordada na nota 1031902.6 se você tiver acesso a ela, ou este explica se você não . Se fosse realmente um número negativo, o último byte hexadecimal deveria ser 66. Despejar o número que parece ser - com um único sinal de menos, não dois, o que não tem sentido - dá:
select dump(-1331013400000000000000000000, 1016) from dual;

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

Criar números inválidos no Oracle não é simples (suponho que você não esperaria que fosse), mas esse é um método que usei antes. Uma das pistas, além do sinal de menos duplo e que todos têm o mesmo comprimento, é que converter o valor despejado de volta em um número não dá o mesmo 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

Isso é do Oracle 9i, o próximo que tenho agora para um banco de dados 8i, então os resultados podem variar um pouco.

Não ser capaz de fazer to_number(value) é uma grande pista também, é claro; há um to_char() implícito quando você faz isso, está tentando converter a representação de texto em um número, o que explica o erro. O to_char() o valor também não corresponde ao que uma seleção simples faz, curiosamente. Você veria o mesmo erro se fizesse isso com seus dados.
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 você saiba de onde vieram os dados incorretos e ainda tenha o original, provavelmente não poderá recuperar esses valores. Acho que o melhor que você pode fazer é ignorá-lo ou substituí-lo por algo que migrará - se o campo for anulável, null seria a opção segura, caso contrário, acho que você teria que escolher um valor mágico.

Identificar e modificar as linhas afetadas pode ser feito por meio de uma função; possivelmente 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;
/

Com o mesmo valor inválido criado anteriormente e um 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

Não é o ideal de forma alguma, mas neste momento acho que você está apenas salvando o que pode. Você pode excluir as linhas em vez de atualizá-las ou definir o valor para outra coisa, depende de como você deseja prosseguir.

Você pode tentar envolver a Oracle para ver se eles conseguem descobrir o que aconteceu e ver se eles têm algum truque para voltar aos valores originais - o que parece improvável - mas não tenho certeza se você obteria muito suporte para uma versão tão antiga do banco de dados.

É claro que, sem saber como e quando a corrupção foi introduzida (por meio de uma importação desonesta, talvez, ou por meio de um programa OCI com erros), você deve questionar a validade de todos os outros dados, tanto nessa coluna quanto em outros lugares. Neste caso, a corrupção parece muito uniforme - todos os valores inválidos parecem ser construídos da mesma maneira - então você pode estar bem. Geralmente, porém, algo que coloca bytes incorretos em um valor interno pode gerar um valor errado, mas ainda válido. Pode parecer certo, ou pode ser ordens de magnitude fora do valor esperado original, e realmente não há como saber.