Domanda

Penso che sia meglio chiederlo sotto forma di un semplice esempio. Il seguente blocco di SQL causa un errore " DB-Library: 20049 Gravità: 4 Messaggio: la conversione dei dati ha provocato un overflow " messaggio, ma come mai?

declare @a numeric(18,6), @b numeric(18,6), @c numeric(18,6)
select @a = 1.000000, @b = 1.000000, @c = 1.000000
select @a/(@b/@c)
go 

In che modo è diverso da:

select 1.000000/(1.000000/1.000000)
go

quale funziona bene?

È stato utile?

Soluzione

Ho riscontrato lo stesso problema l'ultima volta che ho provato a utilizzare Sybase (molti anni fa). Provenendo da una mentalità di SQL Server, non mi rendevo conto che Sybase avrebbe tentato di forzare i decimali - che, matematicamente, è ciò che dovrebbe fare. :)

Dal Sybase manual :

  

Si verificano errori di overflow aritmetico quando   il nuovo tipo ha troppi decimali   luoghi per accogliere i risultati.

E più in basso:

  

Durante conversioni implicite in valori numerici   o tipi decimali, perdita di scala   genera un errore di scala. Utilizzare il   arithabort opzione numeric_truncation   per determinare quanto grave sia un tale errore   è considerato. L'impostazione predefinita,   arithabort numeric_truncation on,   interrompe l'affermazione che causa il   errore ma continua a elaborare altro   dichiarazioni nella transazione o   batch. Se si imposta arithabort   numeric_truncation off, Adaptive   Il server tronca i risultati della query e   continua l'elaborazione.

Quindi supponendo che la perdita di precisione sia accettabile nel tuo scenario , probabilmente vuoi quanto segue all'inizio della tua transazione:

SET ARITHABORT NUMERIC_TRUNCATION OFF

E poi alla fine della transazione:

SET ARITHABORT NUMERIC_TRUNCATION ON

Questo è ciò che mi ha risolto molti anni fa ...

Altri suggerimenti

Questa è solo una speculazione, ma potrebbe essere che il DBMS non guardi il valore dinamico delle tue variabili ma solo i valori potenziali? Pertanto, un valore numerico di sei decimali diviso per un valore numerico di sei decimali potrebbe risultare in un valore numerico di dodici decimali; nella divisione letterale, il DBMS sa che non c'è overflow. Non sei ancora sicuro del motivo per cui al DBMS sarebbe importato, non dovrebbe restituire il risultato di due divisioni a sei decimali fino a un valore numerico a 18 decimali?

Poiché nel primo esempio sono state dichiarate le variabili, si prevede che il risultato sarà della stessa dichiarazione (ovvero numerico (18,6)) ma non lo è.

Devo dire che il primo ha funzionato in SQL2005 (restituito 1.000000 [lo stesso tipo dichiarato]) mentre il secondo ha restituito (1.00000000000000000000000 [una dichiarazione completamente diversa]).

Non direttamente correlato, ma potrebbe far risparmiare un po 'di tempo agli errori di overflow dell'aritmetica utilizzando Sybase ASE (12.5.0.3).

Stavo impostando alcuni valori predefiniti in una tabella temporanea che intendevo aggiornare in seguito e mi sono imbattuto in un errore di overflow aritmetico.

declare @a numeric(6,3)

select 0.000 as thenumber into #test --indirect declare

select @a = ( select thenumber + 100 from #test )

update #test set thenumber = @a

select * from #test

Mostra l'errore:

Arithmetic overflow during implicit conversion of NUMERIC value '100.000' to a NUMERIC field .

Quale nella mia testa dovrebbe funzionare, ma non come la colonna 'thenumber' non è stata dichiarata (o indirettamente dichiarata come decimale (4,3)). Quindi dovresti dichiarare indirettamente la colonna della tabella temporanea con scala e precisione nel formato desiderato, come nel mio caso era 000.000.

select 000.000 as thenumber into #test --this solved it

Speriamo che questo salvi qualcuno :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top