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

Corrupção de data do Oracle durante a atualização


ATUALIZAR:

Não encontro nenhuma referência publicada a esse tipo específico de corrupção de DATE no site de suporte da Oracle. (Pode estar lá, minhas pesquisas rápidas simplesmente não apareceram.)
  • Script incorreto para verificar se há datas corrompidas no banco de dados [ID 95402.1]
  • Bug 2790435 - Serial INSERT com SELECT paralelo e conversão de tipo pode inserir dados corrompidos [ID 2790435.8]

A saída da função DUMP() está mostrando que o valor da data é realmente inválido:
Typ=12 Len=7: 120,110,11,18,13,0,16 

Esperamos que o byte de minutos seja um valor entre um e sessenta, não zero.

Os 7 bytes de um valor DATE representam, em ordem, século(+100), ano(+100), mês, dia, hora(+1), minutos(+1), segundos(+1).

A única vez que vi valores DATE inválidos como este quando um valor DATE estava sendo fornecido como uma variável de ligação, de um programa Pro*C (onde o valor de ligação é fornecido na representação interna de 7 bytes, ignorando inteiramente as rotinas de validação normais que pegar datas inválidas, por exemplo, 30 de fevereiro)

Não há razão para esperar o comportamento que você está vendo, dada a sintaxe do Oracle que você postou.

Esta é uma anomalia espúria (corrupção de memória?) ou se for repetível, então é uma falha (bug) no código Oracle. Se for uma falha no código Oracle, os suspeitos mais prováveis ​​seriam recursos "novos" em uma versão não corrigida.

(Eu sei que CAST é uma função SQL padrão que existe há muito tempo em outros bancos de dados. Acho que sou da velha guarda e nunca a introduzi no meu repertório de sintaxe Oracle. Não sei qual versão do Oracle era essa introduziu o CAST, mas eu teria ficado longe dele na primeira versão em que apareceu.)

A grande 'bandeira vermelha' (que outro comentarista observou) é que CAST( datecol AS DATE) .

Você esperaria que o otimizador tratasse isso como equivalente a date_col ... mas a experiência anterior nos mostra que TO_NUMBER( number_col ) é realmente interpretado pelo otimizador como TO_NUMBER( TO_CHAR ( number_col ) ) .

Suspeito que algo semelhante possa estar acontecendo com esse CAST desnecessário.

Com base nesse registro que você mostrou, suspeito que o problema seja com valores com um valor "59" para minutos ou segundos e, possivelmente, um valor "23" para horas, seriam os que mostrariam o erro.

Eu tentaria verificar lugares onde os minutos, horas ou segundos são armazenados como 0:
SELECT id, DUMP(activitydate)
  FROM newtable
 WHERE DUMP(activitydate) LIKE '%,0,%' 
    OR DUMP(activitydate) LIKE '%,0'