Reputation: 133
I'm trying to write a stored procedure and I'm getting unexpected divide by 0 exceptions.
I've narrowed it down to the following example.
Why in the world does this :
declare @A decimal;
declare @B decimal;
declare @C decimal;
set @A = 4;
set @B = 9;
set @C = @A/@B
select @A/@B as 'Expected'
select @C as 'Wut'
result in this?
Expected
---------------------------------------
0.4444444444444444444
(1 row(s) affected)
Wut
---------------------------------------
0
(1 row(s) affected)
Upvotes: 11
Views: 31967
Reputation: 48016
This is happening because if you don't declare precision and scale, a Decimal defualts to (18, 0)
18 digits to the left of the decimal point, and 0 to the right.
If you change C to be defined like this:
declare @A decimal;
declare @B decimal;
declare @C decimal (18, 9);
set @A = 4;
set @B = 9;
set @C = @A/@B
select @A/@B as 'Expected'
select @C as 'Wut'
You should get a proper answer
Expected
---------------------------------------
0.4444444444444444444
(1 row(s) affected)
Wut
---------------------------------------
0.444444444
(1 row(s) affected)
Upvotes: 1
Reputation: 149000
The problem is that you haven't specified a scale for the decimal
type. From MSDN:
s (scale)
The number of decimal digits that will be stored to the right of the decimal point. This number is substracted from p to determine the maximum number of digits to the left of the decimal point. Scale must be a value from 0 through p. Scale can be specified only if precision is specified. The default scale is 0; therefore, 0 <= s <= p.
So when you try to store @A/@B
back into @C
, the fractional part gets truncated.
Notice:
declare @A decimal(18, 3);
declare @B decimal(18, 3);
declare @C decimal(18, 3);
set @A = 4;
set @B = 9;
set @C = @A/@B
select @A/@B -- 0.44444444444444444444
select @C -- 0.444
Upvotes: 13