sql >> Databasteknik >  >> RDS >> Oracle

Oracle datum korruption under uppdatering

UPPDATERING:

Jag hittar ingen publicerad referens till denna specifika typ av DATE-korruption på Oracles supportwebbplats. (Det kan finnas där, mina snabba sökningar visade det bara inte.)

  • Baddate-skript för att kontrollera databas efter korrupta datum [ID 95402.1]
  • Bug 2790435 – Serial INSERT med parallell SELECT och typkonvertering kan infoga korrupta data [ID 2790435.8]

Utdata från DUMP()-funktionen visar att datumvärdet verkligen är ogiltigt:

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

Vi förväntar oss att minutbyten ska vara ett värde mellan ett och sextio, inte noll.

De 7 byten av ett DATUM-värde representerar, i ordning, århundrade(+100), år(+100), månad, dag, timme(+1), minuter(+1), sekunder(+1).

Den enda gången jag har sett ogiltiga DATE-värden som detta när ett DATE-värde tillhandahölls som en bindningsvariabel, från ett Pro*C-program (där bindningsvärdet tillhandahålls i den interna 7-byte-representationen, helt förbi de normala valideringsrutinerna som fånga ogiltiga datum, t.ex. 30 februari)

Det finns ingen anledning att förvänta sig det beteende du ser, med tanke på Oracle-syntaxen du postade.

Detta är antingen en falsk anomali (minneskorruption?) eller om detta kan upprepas, så är det ett fel (bugg) i Oracle-koden. Om det är ett fel i Oracle-koden, skulle de mest troliga misstänkta vara "nya" funktioner i en icke-patchad version.

(Jag vet att CAST är en standard SQL-funktion som har funnits i evigheter i andra databaser. Jag antar att jag är gammal och har aldrig introducerat den i min Oracle-syntaxrepertoar. Jag vet inte vilken version av Oracle det var som introducerade CAST, men jag skulle ha hållit mig borta från den i den första releasen den dök upp i.)

Den stora "röda flaggan" (som en annan kommentator noterade) är att CAST( datecol AS DATE) .

Du skulle förvänta dig att optimeraren skulle behandla det som likvärdigt med date_col ... men tidigare erfarenhet visar att TO_NUMBER( number_col ) tolkas faktiskt av optimeraren som TO_NUMBER( TO_CHAR ( number_col ) ) .

Jag misstänker att något liknande kan hända med den där onödiga CAST.

Baserat på den posten du visade, misstänker jag att problemet är med värden med ett "59"-värde för minuter eller sekunder, och möjligen ett "23"-värde för timmar, skulle vara de som visar felet.

Jag skulle försöka leta efter platser där minuterna, timmarna eller sekunderna lagras som 0:

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


  1. Att använda OR on WHERE-satsen i MySql orsakar långsam exekvering

  2. MySQL hittar alla föräldrar rekursivt

  3. Använder Dapper och Postgresql - citext datatyp

  4. Analysera en xml-fil och lagra den i en databas