Errore 2570 e "data purity"

Eseguendo il comando DBCC CHECKDB con l'opzione WITH DATA_PURITY, ho evidenziato degli errori su un database; i messaggi erano una sfilza di errori 2570 come questo qui sotto

Msg 2570, Level 16, State 3, Line 1

Page (1:6672), slot 24 in object ID 997578592, index ID 1, partition ID 72057594241351680, alloc unit ID 72057594246987776 (type "In-row data"). Column "IMP_MOV_SIN" value is out of range for data type "decimal". Update column to a legal value.

Si trattava di ben 126 eventi, tutti sulla stessa tabella, e tutti sul medesimo campo (in realtà erano 63 errori nelle pagine dati ed altrettanti in un indice non clustered dove il campo era nella clausola INCLUDE). Una ricerca nella kb mi portava a questo articolo che dava anche una soluzione per venire a capo del problema. Si trattava quindi di individuare, con una query, quali erano i record fuori dal range ammesso per il tipo dati in questione. Trattandosi di un campo definito come DECIMAL (11, 2), eseguivo l'istruzione

SELECT *
FROM dbo.Tabella
WHERE IMP_MOV_SIN > 999999999.99
    OR IMP_MOV_SIN < 999999999.99

come suggerito dall'articolo stesso. Questa query però non restituiva alcun record ed anche ci fosse stato qualche record "out-of-range" il problema successivo sarebbe stato quello di riportare il valore "in-range". Si, ma come...? Come avrei potuto scegliere arbitrariamente un valore per ciascuna delle 126 occorrenze dell'errore? Si sarebbe reso necessario comunque l'intervento dell'utente per bonificare tali dati con valori esatti e non solo congruenti.

Tuttavia se non c'erano valori "out-of-range" qualcosa doveva essere successo a quei 63 record, ma cosa? Beh, senza pensarci troppo ho fatto qualche tentativo nell'ambiente di test ampliando il datatype da un DECIMAL(11, 2) ad un DECIMAL(38, 20) per poi riportarlo a quello originario. Ho pensato che se il problema fosse dipeso dal fatto che qualcuno di quei 63 record avesse un numero "errato" di decimali avrei così sistemato il problema. Beh, la cosa ha funzionato! Cool

Prove successive, ripristinando nuovamente il database corrotto nel solito ambiente di test, mi hanno fatto trovare una soluzione ancora migliore, ovvero quella di fare un update del genere

UPDATE dbo.Tabella
SET IMP_MOV_SIN = IMP_MOV_SIN * 1

ed anche questa soluzione avrebbe risolto il problema in maniera più efficace rispetto alla modifica del datatype (nel frattempo avevo già corretto con la prima soluzione l'ambiente di produzione).

Spero che possa tornare utile a qualcuno... Wink

 

Bye

 

 

Published venerdì 5 settembre 2008 8.12 by lbianchi
Filed under:

Comments

No Comments