Oracle
 sql >> Database >  >> RDS >> Oracle

Danneggiamento della data di Oracle durante l'aggiornamento

AGGIORNAMENTO:

Non trovo alcun riferimento pubblicato a questo specifico tipo di danneggiamento DATE sul sito di supporto Oracle. (Potrebbe essere lì, le mie ricerche rapide non sono riuscite.)

  • Script di Baddate per verificare la presenza di dati corrotti nel database [ID 95402.1]
  • Bug 2790435 - Serial INSERT con SELECT parallela e conversione del tipo può inserire dati corrotti [ID 2790435.8]

L'output della funzione DUMP() mostra che il valore della data non è valido:

Typ=12 Len=7: 120,110,11,18,13,0,16 

Ci aspettiamo che il byte dei minuti sia un valore compreso tra uno e sessanta, non zero.

I 7 byte di un valore DATE rappresentano, in ordine, secolo(+100), anno(+100), mese, giorno, ora(+1), minuti(+1), secondi(+1).

L'unica volta in cui ho visto valori DATE non validi come questo quando un valore DATE veniva fornito come variabile di collegamento, da un programma Pro*C (dove il valore di collegamento è fornito nella rappresentazione interna a 7 byte, ignorando completamente le normali routine di convalida che cattura date non valide, ad es. 30 febbraio)

Non c'è motivo di aspettarsi il comportamento che stai vedendo, data la sintassi Oracle che hai pubblicato.

Questa è un'anomalia spuria (danneggiamento della memoria?) o se è ripetibile, allora è un difetto (bug) nel codice Oracle. Se si tratta di un difetto nel codice Oracle, i sospetti più probabili sarebbero le funzionalità "nuove" in una versione senza patch.

(So ​​che CAST è una funzione SQL standard che esiste da anni in altri database. Immagino di essere della vecchia scuola e non l'ho mai introdotta nel mio repertorio di sintassi Oracle. Non so quale versione di Oracle fosse quella ha introdotto il CAST, ma ne sarei rimasto alla larga nella prima versione in cui è apparso.)

La grande "bandiera rossa" (che un altro commentatore ha notato) è che CAST( datecol AS DATE) .

Ti aspetteresti che l'ottimizzatore lo consideri equivalente a date_col ... ma l'esperienza passata ci mostra che TO_NUMBER( number_col ) viene effettivamente interpretato dall'ottimizzatore come TO_NUMBER( TO_CHAR ( number_col ) ) .

Sospetto che qualcosa di simile possa succedere con quel CAST non necessario.

Sulla base di quel record che hai mostrato, sospetto che il problema riguardi valori con un valore "59" per minuti o secondi, e possibilmente un valore "23" per ore, sarebbero quelli che mostrano l'errore.

Proverei a cercare i luoghi in cui i minuti, l'ora oi secondi sono memorizzati come 0:

SELECT id, DUMP(activitydate)
  FROM newtable
 WHERE DUMP(activitydate) LIKE '%,0,%' 
    OR DUMP(activitydate) LIKE '%,0'