Earlier I wrote SQL SERVER – Challenge – Puzzle – Usage of FAST Hint and I did receive some good comments. Here is another question to tease your mind. Run following script and you will see that it will thrown an error.

`DECLARE @mymoney MONEY;`

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(5,2)) MoneyInt;

GO

The datatype of money is also visually look similar to the decimal, why it would throw following error:

Msg 8115, Level 16, State 8, Line 3

Arithmetic overflow error converting money to data type numeric.

Please leave a comment with explanation and I will post a your answer on this blog with due credit.

Reference: **Pinal Dave (****http://blog.sqlauthority.com****)**

## 27 comments. Leave new

Buena respuesta, me sirvio

Numeric data types that have fixed precision and scale.

decimal[ (p[ , s] )] and numeric[ (p[ , s] )]

p (precision) :

The maximum total number of decimal digits that can be stored, both to the left and to the right of the decimal point.

s (scale) :

The maximum number of decimal digits that can be stored to the right of the decimal point.

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(5,2)) MoneyInt;

SIR HERE THE DECIMAL VALUE ACCEPT

DECIMAL(TOTAL DIGIT,DECIMAL POINT AFTER DIGIT)

SO USE

SELECT CAST(@mymoney AS DECIMAL(7,2)) MoneyInt;

IT WILL RUN

Decimal data type is defined as Decimal (Precision, Scale).

Precision includes Scale.

So Decimal (5,2) actually means, we can have 3 digits before decimal and 2 digits after decimal.

From above example, (3+2) digits is called as precision and 2 digits after decimal is callled as scale.

In your example, you have 5 digits before decimal and 2 digits after decimal, therefore the correct decimal should be Decimal (7,2).

~ IM.

You are taking 5 in place of 7.Because here length of This Money type variable will be fit in 5 digit before decimal point so you should take at least 5 digit in decimal datatype. digit after decimal will be round off.

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(7,2)) MoneyInt;

You need to define the decimal larger to cast money to

Yes I agree with Fbncs.

Just adding description for whay it’s filing when we rty to convert it to Decimal(5,2)

In decimal decalaration, DECIMAL(P,S), P (precision) specifies the number of digits on both side of decimal point. 12345.67 has 7 digits ( of 2 digits are of scale), so we need decimal(5,2) for storing this number.

Even if we tries to convert the number to DECIMAL(7,3), we get same error as we specify scale as 3 and so, we can have only 4 digits on left side of decimal point.

-Chintak

Hi Pinal,

The overflow problem is because the length of DECIMAL(5,2) is small to support this value.

In this case, the value 12345.67 has length (precision) of 7 digits, when 2 digits are dedicated to “.67” (scale), then you can convert this number to a DECIMAL(7,2) and not to a DECIMAL(5,2).

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(7,2)) MoneyInt;

GO

But you can lost the 2 digits dedicated to “.67”, if you use a small decimal with a compatible precision without scale:

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(5,0)) MoneyInt;

GO

Query from “fbncs” is correct because decimal data type takes 2 bytes of overhead to store the offset to the value. Which money don’t. Thats why converting from money to decimal need 2 bytes extra otherwise enjoy arithmetic overflow error ;)

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(7,2)) MoneyInt;

GO?

Now it will not through any error.

Since @mymoney variable has 5 digits before decimal and 2 digits after decimal. So we have to put 7 insead of 5 in precision of DECIMAl Datatype, because 5 + 2 = 7 means total no of digits that DECIMAL datatype may contain before decimal and after decimal place.

For understanding, you can also see it like this DECIMAL((7-2),2).

Have a look the detail given below for more clarity-

DECIMAL(p,s)

p (precision)

The maximum total number of decimal digits that can be stored, both to the left and to the right of the decimal point.

s (scale)

The maximum number of decimal digits that can be stored to the right of the decimal point.

Hi pinal

as per the bol.

In Transact-SQL statements, a constant with a decimal point is automatically converted into a numeric data value, using the minimum precision and scale necessary. For example, the constant 12345.67 is converted into a numeric value with a precision of 7 and a scale of 2.

bol link : http://msdn.microsoft.com/en-us/library/ms191530.aspx

section : Converting decimal and numeric Data

DECIMAL(5,2) has 5 precision and 2 scale.

Precision is the total number of digits in a number.

Scale is the number of digits to the right of the decimal point in a number.

For Example the number 8714.235 has a

precision – 7

scale – 3

You need to specify

DECLARE @mymoney MONEY;

SET @mymoney = -12345.67;

SELECT CAST(@mymoney AS DECIMAL(7,2)) MoneyInt;

Because…

Here first part specifies total number of decimals. i.e. number of characters before “Period” (.) + number of characters after “Period” (.)

5+2 = 7

Second part sepcifies how many characters should be after “Period” (.)

you must do :

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(abc,2)) MoneyInt;

you have 7 digits in @mymoney (including decimals) so you put abc=7 or greater than 7

you must do :

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(,2)) MoneyInt;

you have 7 digits in @mymoney (including decimals)

Another approach (NOT RECOMMENDED)

SET ARITHABORT OFF

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(5,2)) MoneyInt;

GO

The above method is the way to silently fail the conversions, in which case the CAST function will return a NULL Value. Notice the SET statement that explicitly sql server to ignore arithmetic overflows.

Having said that, this approach is not a recommended practice and should not be used any environment (DEV,QA,STAG,PROD).

In Your question while you converting money to decimal you are using decimal(5,2) that means 2 is precision in total number 5 digit including precision that means only 3 digit and your money value is greater then hundred

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(7,2)) MoneyInt;

GO

The target data type is unable to accommodate needful value. We will need to give enough room by expanding the Decimal value and precision.

You need to increase the size of precision. You need to make it 7 or above.

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(7,2)) MoneyInt;

GO

O/P-> 12345.67

Thanks & Regards,

Piyush srivastava

Mumbai

The money data type goes out to 4 places after the decimal.

Your data type @mymoney is set to round to the nearest penny (2 places). SQL cannot handle the conversion and will throw out the overflow error.

Try SELECT CAST(@mymoney AS DECIMAL(5,4)) MoneyInt;

As with the original post, this is wrong, DECIMAL(5,4) would hold for example, 1.2345, the first number is the total length, the second number is the decimal points

you must do :

DECLARE @mymoney MONEY;

SET @mymoney = 12345.67;

SELECT CAST(@mymoney AS DECIMAL(7,2)) MoneyInt;

you have 7 digits in @mymoney (including decimals)

Indeed!!!

I agree with fbncs.

Exactly. It’s not 5 number followed by 2 numbers. 5, 2 means that it’s 5 digits in total with 2 after the decimal point. To represent the number you show, it needs a total of 7 with 2 after the decimal place and 5 before.

shure, but don’t forget… if you have 4 decimals in @mymoney, you’ll lost information doing this convertion. The most correclty to do in that case is DECIMAL(9,4).

Exactly, first digit shows the total length