Difference between Numeric and Decimal in SQL - sql

What's the difference between numeric[(p[,s])] and decimal[(p[,s])] as SQL datatype?

NUMERIC(p, s) takes two arguments: precision (p) and scale (s). Numeric datatype enforces the exact precision and scale that you have specified.
On other side, DECIMAL(p, s) also takes the same two arguments. However, with the DECIMAL data type, the precision can be greater than the value you have supplied. Thus, this data type can provide you with more flexibility.

Related

How to store NUMERIC value as given in SQL Server

In Oracle when you have a NUMBER data type and do not specify precision and scale like NUMBER(18,2) for example and use it like this NUMBER instead it will store the value as given.
From the manual
If a precision is not specified, the column stores values as given
Now I want to know if there is a way to let NUMERIC data type in SQL Server do the same. I have to use NUMERIC and not DECIMAL or other data types and I am not allowed to specify the precision or scale since I have no possibility to test if the data that will be used will cause errors because I have no access to the data. I just know that the data did not cause any trouble with our Oracle database which uses only NUMBER datatype without any specifications.
No, numeric needs a precision and scale and has defaults if none are set. Simple like that.
https://learn.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-server-2017
Quote:
decimal[ (p[ ,s] )] and numeric[ (p[ ,s] )] Fixed precision and scale
numbers. When maximum precision is used, valid values are from - 10^38
+1 through 10^38 - 1. The ISO synonyms for decimal are dec and dec(p, s). numeric is functionally equivalent to decimal.
Like often, documentation is your friend.

float or double precision

When I tell postgreSQL to show a column as float, I always get as a result "double precision".
Is it the same?
Like Damien quoted from the documentation:
PostgreSQL also supports the SQL-standard notations float and float(p) for specifying inexact numeric types.
Here, p specifies the minimum acceptable precision in binary digits.
PostgreSQL accepts float(1) to float(24) as selecting the real type,
while float(25) to float(53) select double precision.
Values of p outside the allowed range draw an error.
float with no precision specified is taken to mean double precision.
PostgreSQL, like other databases, supports the SQL standard by supplying an appropriate data type when a certain SQL standard type is requested. Since real or double precision fit the bill here, they are taken instead of creating new redundant types.
The disadvantage is that the data type of a column may read different from what you requested, but as long as it handles your data the way it should, is that a problem?

Which is more suitable for prices calculations in Firebird: decimal or numeric?

In Firebird DB: I read about the difference between numeric and decimal but still not sure Which is more suitable for prices calculations: decimal or numeric without rounding numbers?
The implementation for both NUMERIC and DECIMAL are almost identical in Firebird. The Interbase 6.0 Data Definition Guide says there is a subtle difference (for NUMERIC precision is exactly as declared, for DECIMAL the precision is at least equal to declared). According to The Firebird Book by Helen Borrie there is only a difference for numbers with a precision of less than 5 as a NUMERIC of precision 1-4 is mapped to a SMALLINT while a DECIMAL of precision 1-9 is mapped to INTEGER. This book also remarks that both NUMERIC and DECIMAL conform to the behavior of the SQL-92 type DECIMAL.
So with that said, I'd advise to go for DECIMAL, as its behaviour conforms to that defined in the SQL standards and therefor holds less surprise for people unfamiliar with Firebird, but who do understand the standard behaviour.
They're both equally suitable for price calculations. But there will always be certain kinds of calculations that require rounding, no matter which of these you use.
Decimal is the more flexible of the two.

Float type in MySQL

I have a MySQL table with column of type float(10, 6).
If I insert 30.064742 into the column the value stored in the database is 30.064741.
Why?
Floating-point numbers imply a certain amount of imprecision. Use a DECIMAL column if you need to be certain to retain every digit.
It's a general problem with rounding numbers to a precision which can be stored in the database. Floats will round to multiples of powers of two. If you want something that is easier to think about, you can use the Decimal type, which will round to powers of ten.
More details in the documentation for numeric types:
When such a column is assigned a value with more digits following the decimal point than are allowed by the specified scale, the value is converted to that scale. (The precise behavior is operating system-specific, but generally the effect is truncation to the allowable number of digits.)

SQL Server: Calculation with numeric literals

I did some testing with floating point calculations to minimize the precision loss. I stumbled across a phenomen I want to show here and hopefully get an explanation.
When I write
print 1.0 / (1.0 / 60.0)
the result is
60.0024000960
When I write the same formula and do explicit casting to float
print cast(1.0 as float) / (cast(1.0 as float) / cast(60.0 as float))
the result is
60
Until now I thought that numeric literals with decimal places are automatically treated as float values with the appropriate precision. Casting to real shows the same result as casting to float.
Is there some documentation on how SQL Server evaluates numeric literals?
Of what datatype are those literals?
Do I really have to cast them to float get better precision (which sounds like irony to me :)?
Is there an easier way than cluttering my formulas with casts?
SQL Server uses the smallest possible datatype.
When you run this script
SELECT SQL_VARIANT_PROPERTY(1.0, 'BaseType')
SELECT SQL_VARIANT_PROPERTY(1.0, 'Precision')
SELECT SQL_VARIANT_PROPERTY(1.0, 'Scale')
SELECT SQL_VARIANT_PROPERTY(1.0, 'TotalBytes')
you'll see that SQL Server implicitly used a NUMERIC(2, 1) datatype.
The division by 60.0 converts the result to NUMERIC(8, 6).
The final calculation converts the result to NUMERIC(17, 10).
Edit
Taken from SQL Server Books Online Data Type Conversion
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
12.345 is converted into a numeric value with a precision of 5 and a
scale of 3.
Yes, you frequently have to cast them to float get better precision. My take on it:
For better precision cast decimals before calculations
I think it should be understood what is going on behind the scenes for future reference in similar cases.
Literal numerical values with decimal point excluding scientific notation represent Decimal data type which is stored as smallest possible Decimal type. Same quote as Lieven Keersmaekers's from:
https://msdn.microsoft.com/en-us/library/ms191530%28SQL.90%29.aspx#_decimal
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 12.345 is
converted into a numeric value with a precision of 5 and a scale of 3.
The trailing zeros on the right of decimal point specify scale. The leading zeros left of decimal point are ignored.
Some examples:
1.0 -> Decimal(2,1)
60.0 -> Decimal(3,1)
1.00 -> Decimal(3,2)
01.0 -> Decimal (2,1)
Another point to consider is Data Type precedence.
When an operator combines two expressions of different data types, the rules for data type precedence specify that the data type with the lower precedence is converted to the data type with the higher precedence.
And yet another point to consider is if we do arithmetic operations on Decimal types that the resulting Decimal type, i.e. precision and scale depend on both operands and operation itself. This is described in document Precision, Scale, and Length.
So, part of your expression in parenthesis
( 1.0 / 60.0 ) is evaluated to 0.016666 and the resulting type is Decimal (8,6)
using above rules about Precision and scale of Decimal expressions. In addition the banker's rounding or rounding to even is used. It is important to note different rounding for Decimal and float type are used.
If we continue the expression
1.0 / 0.016666 is evaluated to 60.002400096 and the resulting type is Decimal (17,10)
So the part of the discrepancy is due to different rounding being used for decimal types than for float.
In accordance to the above rules it would be sufficient to use just one cast inside parenthesis. Every other literal will be promoted to float in accordance with Data Type Precedence rules.
1.0 / (1.0 / cast(60.0 as float))
And one more IMPORTANT thing. Even this float expression does not calculate exact result. It is just so that the front end (SSMS or whatever) rounds the value to (I guess) precision 6 digits and then truncates trailing zeros. So i.e. 1.000001 becomes 1.
Simple, isn't it?
To write a constant float expression, try to use scientific notation:
select (1.0E0 / (1.0E0 / 60.0E0))
The result is 60.