Appropriate datatype for holding percent values?
Assuming two decimal places on your percentages, the data type you use depends on how you plan to store your percentages:
- If you are going to store their fractional equivalent (e.g. 100.00% stored as 1.0000), I would store the data in a
decimal(5,4)
data type with aCHECK
constraint that ensures that the values never exceed 1.0000 (assuming that is the cap) and never go below 0 (assuming that is the floor). - If you are going to store their face value (e.g. 100.00% is stored as 100.00), then you should use
decimal(5,2)
with an appropriateCHECK
constraint.
Combined with a good column name, it makes it clear to other developers what the data is and how the data is stored in the column.
- Hold as a
decimal
. - Add check constraints if you want to limit the range (e.g. between 0 to 100%; in some cases there may be valid reasons to go beyond 100% or potentially even into the negatives).
- Treat value 1 as 100%, 0.5 as 50%, etc. This will allow any math operations to function as expected (i.e. as opposed to using value 100 as 100%).
- Amend precision and scale as required (these are the two values in brackets
columnName decimal(precision, scale)
. Precision says the total number of digits that can be held in the number, scale says how many of those are after the decimal place, sodecimal(3,2)
is a number which can be represented as#.##
;decimal(5,3)
would be##.###
. -
decimal
andnumeric
are essentially the same thing. Howeverdecimal
is ANSI compliant, so always use that unless told otherwise (e.g. by your company's coding standards).
Example Scenarios
- For your case (0.00% to 100.00%) you'd want
decimal(5,4)
. - For the most common case (0% to 100%) you'd want
decimal(3,2)
. - In both of the above, the check constraints would be the same
Example:
if object_id('Demo') is null
create table Demo
(
Id bigint not null identity(1,1) constraint pk_Demo primary key
, Name nvarchar(256) not null constraint uk_Demo unique
, SomePercentValue decimal(3,2) constraint chk_Demo_SomePercentValue check (SomePercentValue between 0 and 1)
, SomePrecisionPercentValue decimal(5,2) constraint chk_Demo_SomePrecisionPercentValue check (SomePrecisionPercentValue between 0 and 1)
)
Further Reading:
- Decimal Scale & Precision: http://msdn.microsoft.com/en-us/library/aa258832%28SQL.80%29.aspx
-
0 to 1
vs0 to 100
: C#: Storing percentages, 50 or 0.50? - Decimal vs Numeric: Is there any difference between DECIMAL and NUMERIC in SQL Server?
I agree with Thomas and I would choose the DECIMAL(5,4) solution at least for WPF applications.
Have a look to the MSDN Numeric Format String to know why : http://msdn.microsoft.com/en-us/library/dwhawy9k#PFormatString
The percent ("P") format specifier multiplies a number by 100 and converts it to a string that represents a percentage.
Then you would be able to use this in your XAML code:
DataFormatString="{}{0:P}"