So che questo è abbastanza una vecchia questione, ma nessuna delle risposte esistenti sembrano affrontare il "perché?" aspetto alla tua domanda.
Innanzitutto, qual è il tipo di dati per le espressioni letterali? Non ero sicuro (e non guardare in su) così mi sono imbattuto il seguente:
select 1.4 union all
select 'frob'
che restituisce l'errore:
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
Okay, quindi 1.4
e gli altri letterali sono numeric
- alias decimal
.
Avanti, qual è il tipo di ritorno della funzione SUM
, se superato un decimal(p,s)
:
decimal(38, s)
Va bene, in modo che i tipi di dati delle 3 SUM
espressioni nella query sono decimal(38,1)
, decimal(38,4)
e decimal(38,2)
.Dati questi 3 tipi di dati disponibili, decimal(38,1)
è il tipo scelto finale, in base alle regole per differing precisions and scales.
The result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.
Così, finalmente, di nuovo alla documentazione su decimal
:
By default, SQL Server uses rounding when converting a number to a decimal or numeric value with a lower precision and scale. However, if the SET ARITHABORT option is ON, SQL Server raises an error when overflow occurs. Loss of only precision and scale is not sufficient to raise an error.
Ecco, questo è il risultato finale.
In un primo momento questo tipo può sembrare sorprendente, fino a quando ti rendi conto che in generale, sum
opererà contro più righe ed è facilmente possibile per più valori di una data precisione e la scala a traboccare il proprio tipo di dati. decimal(38,s)
offre lo spazio più ampio possibile per contenere eventuali overflow senza perdere precisione, per un particolare SUM()
occorrenza e significa che il tipo di dati finale può essere deciso prima dell'esecuzione della query.