2009-09-21 11 views
8

Quando 2 numeri decimali (30,10) sono suddivisi in Sql Server 05, 2 ultimi decimali sembrano essere persi (non arrotondati, semplicemente troncati).Decimale server Sql (30,10) che perde gli ultimi 2 decimali

Ad esempio:

Declare @x decimal(30,10) 
Declare @y decimal(30,10) 
Declare @z decimal(30,10) 

select @x = 2.1277164747 
select @y = 4.8553794574 

Select @z = @y/@x 
select @z 

Risultato: 2,28196731

Ma se 2 numeri che sono divisi vengono convertiti a stare a galla che sembra funzionare:

.... 
Select @z = cast(@y as float)/cast(@x as float) 
select @z 

Risultato: 2,28,196731 millions

Perché Sql sta facendo questo? E qual è il modo giusto di dividere i decimali senza perdere la precisione in Sql.

+0

Buona domanda. Ciò che è ancora più strano è che la modifica delle dichiarazioni a (** 38 **, 10) lo rende effettivamente * peggio *, mentre cambiarle in (** 20 **, 10) sembra effettivamente risolverlo. Non ha senso ... – RBarryYoung

risposta

17

La precisione massima consentita in SQL Server è 38. Si utilizza Decimale (30,10). Il valore massimo è 99,999,999,999,999,999,999,9999,99999 se si divide questo numero per 0,000000001, si otterrà un numero ancora maggiore, quindi il tipo di dati risultante deve essere in grado di accoglierlo. Questo ti fa perdere una certa precisione.

Modificare i tipi di dati originali in Decimale (20,10) e questo problema non si verifica.

Per le regole complete per quanto riguarda i tipi di dati (e come essi sono influenzati dalle operazioni matematiche):

Full rules here

+0

Questa è la risposta corretta. SQL Server determina una precisione e una scala per il risultato in base alla precisione e alla scala degli input * tipi *, non dei valori di input *. Quindi, il risultato è calcolato come decimale (30,8) e poi convertito in decimale (30,10) per essere memorizzato in @z. – richardtallent

+0

Questo ha senso, ma >> Questo ti fa perdere un po 'di precisione <<. Non sarebbe così male se Sql dovesse arrotondare a 8 decimali, ma si limitava a tagliare gli ultimi 2 decimali causando risultati errati. Dovrebbe almeno dare qualche tipo di avvertimento, o anche attraverso un errore quando ciò accade – WebMatrix

+0

Una cosa che le persone sembrano perdere in particolare è che la scala viene ridimensionata a 6 cifre quando si effettua la divisione su 2 numeri di massima precisione. Decimale (38,10)/decimale (38,10) = decimale (38,6). A un certo punto mi sono imbattuto in una spiegazione in cui dovevano farlo per proteggere la precisione nel funzionamento interno in caso di trabocco. – DaveE

-1

In breve, utilizzare la trasmissione per garantire i risultati. Quando assegni @x e @y ai valori letterali, probabilmente stanno adottando la precisione di quei letterali. Questo aiuta a spiegare perché la divisione in base a tali valori non soddisfa le tue aspettative.

+0

se esegui _SELECT @ x, @ y_ vedrai che @x e @y contengono tutte le cifre decimali –

+0

I valori letterali di @x e @y sono memorizzati correttamente, è il risultato memorizzato in @ z che viene troncato. – richardtallent

+0

@ Tutti ... grazie per i chiarimenti. –

Problemi correlati