SQL - Float number appears as XE-05 - sql

I am inserting float numbers in Microsoft SQL and some of them appears as:
7E-05
5E-05
6E-05
The other float are inserted as expected.
For example this float 0.00007 is inserted as 7E-05 but this one 0.01500 as 0.015.
I was suspecting the size of float but after reducing it to x.yyyyy I still get this kind of float.
Anyone know what causing this issue?

If you want to store values like this, use DECIMAL instead of FLOAT in following: DECIMAL(18,5) It will allow your to store number with 5 digits after ,
Sample:
CREATE TABLE #test
(
ID DECIMAL(18,5)
)
INSERT INTO #Test VALUES (0.00007)
SELECT ID FROM #Test
DROP TABLE #Test
Result:
0.00007
As Jon Skeet said:
You're not actually trying to save 123.66, because you can't represent
123.66 exactly as a float or double. The database is saving the data more accurately than you're used to, that's all.
If you want to save decimal numbers accurately, use the decimal type.
You can read more at:
Link 1
Link 2
Link 3
Link 4

Related

SQL: Casting a Float field to NVARCHAR

I have a table with one float field:
CREATE TABLE IMPORTES (IMPORTE FLOAT)
Then I run these instructions:
INSERT INTO IMPORTES (IMPORTE) VALUES (15226.25)
INSERT INTO IMPORTES (IMPORTE) VALUES (9999.25)
INSERT INTO IMPORTES (IMPORTE) VALUES (5226.25)
When I execute SELECT CAST(IMPORTE AS NVARCHAR(40)), the biggest value gets rounded so that 15226.25 becomes 15226.3. Why is that? How can I make the Cast but still get the same value?
According to the documentation here for CAST and CONVERT, for float and real expressions, the style argument to CONVERT defaults to 0, which returns a maximum of 6 digits. Apparently CAST is actually calling CONVERT with this default value "under the hood", so to speak. The only way you are going to get consistent results is if you change the data type of IMPORTE to numeric(18,2), for instance, if you always know that you will only have 2 decimal places.

SQL Server: error converting data type nvarchar to float

I have read many articles and tried several methods but don't have any luck.
I am importing table A (whose cost is char to table B (which requires float).
What I tried:
--cast([Cost] as float)
-- cast(ISNULL([Cost],0) as float)
-- NULLIF(CAST(ISNULL([Cost],0) as float), 0)
convert(float,replace([Cost],',','') )[Cost]
Sample data
FINAL Freight Cost
1248
1248
193.79
201.56
1475.71
97.86
97.86
97.86
125.49
97.86
447.83
450
492.99
450
And I still get this error:
Error converting data type nvarchar to float
Update:
In addition, I am not sure how to modify the existing code based on the answers;
The existing code structure
1. creat table B
2. insert into B () select[DestAddress], [COST] from A
I also tried CAST(test AS FLOAT) AS CastedValue
Why float? The dataset will be sent to an optimization algorithm which requires float. Thanks for pointing it out though.
This works for me?
DECLARE #tbl TABLE(test NVARCHAR(100));
INSERT INTO #tbl VALUES
('1248')
,('1248')
,('193.79')
,('201.56')
,('1475.71')
,('97.86')
,('97.86')
,('97.86')
,('125.49')
,('97.86')
,('447.83')
,('450')
,('492.99')
,('450');
SELECT *
,CAST(test AS FLOAT) AS CastedValue
FROM #tbl;
But the main question is: Why?
Hint 1: Float is the wrong type for this!
From the column name I take, that you are dealing with costs. The FLOAT type is absolutely to be avoided here! You should use DECIMAL or specialised types to cover money or currency values...
Hint 2: NVarchar is the wrong type for this!
And the next question is again: Why? Why are these values stored as NVARCHAR? If ever possible you should solve your problem here...
UPDATE
You edited your question and added this
insert into B () select[DestAddress], [COST]
I do not know the target table's column names, but this should work
INSERT INTO B(ColumnForAddress,ColumnForCost)
SELECT CAST([COST] AS FLOAT),[DestAddress] FROM YourSourceTable
UPDATE 2
After all your comments I'm pretty sure, that there are invalid values within your numbers list. Use ISNUMERIC or - if you are using SQL-Server-2012+ even better TRY_CAST to find invalid values.
Use Convert function , it works smoothly even adding spaces , so there is no need for using Ltrim or Rtrim!
Example:
select convert(float,' 492.99 ') + 1 as converted
Result:
Converted
---------
493.99
FORMAT(ROUND(cast(Total as float), 2), 'C') AS GrandTotal

SQL query defining Column type as float with 3 decimal numbers

This is a simple example of what is not working for me:
CREATE TABLE Vertex(
PointID CHARACTER(15) PRIMARY KEY,
Height FLOAT(6,3)
);
After input like this:
INSERT INTO Vertex values("Tryout 1",555.22689562);
I expect the Height to be saved with the value: 555.227
However it is not the case for me, I keep finding the whole number being saved.
Could you point me to an alternate of how to define a column type and contain the format xxxxxx.xxx
Change float to decimal and it will work.
Height decimal(6,3)
Float is an approximate number data type. Using float may cause loss of precision, and using float data type for equality may not work all times.
Decimal data type is fixed precision data type. For using decimal data types, you will need to convert to the data type like convert(decimal(6,3), <number>).
In case of insert query, it is done implicitly though.

SQL server 'like' against a float field produces inconsistent results

I am using LIKE to return matching numeric results against a float field. It seems that once there are more than 4 digits to the left of the decimal, values that match my search item on the right side of the decimal are not returned. Here's an example illustrating the situation:
CREATE TABLE number_like_test (
num [FLOAT] NULL
)
INSERT INTO number_like_test (num) VALUES (1234.56)
INSERT INTO number_like_test (num) VALUES (3457.68)
INSERT INTO number_like_test (num) VALUES (13457.68)
INSERT INTO number_like_test (num) VALUES (1234.76)
INSERT INTO number_like_test (num) VALUES (23456.78)
SELECT num FROM number_like_test
WHERE num LIKE '%68%'
That query does not return the record with the value of 12357.68, but it does return the record with the value of 3457.68. Also running the query with 78 instead of 68 does not return the 23456.78 record, but using 76 returns the 1234.76 record.
So to get to the question: why having a larger number causes these results to change? How can I change my query to get the expected results?
The like operator requires a string as a left-hand value. According to the documentation, a conversion from float to varchar can use several styles:
Value Output
0 (default) A maximum of 6 digits. Use in scientific notation, when appropriate.
1 Always 8 digits. Always use in scientific notation.
2 Always 16 digits. Always use in scientific notation.
The default style will work fine for the six digits in 3457.68, but not for the seven digits in 13457.68. To use 16 digits instead of 6, you could use convert and specify style 2. Style 2 represents a number like 3.457680000000000e+003. But that wouldn't work for the first two digits, and you get an unexpected +003 exponent for free.
The best approach is probably a conversion from float to decimal. That conversion allows you to specify the scale and precision. Using scale 20 and precision 10, the float is represented as 3457.6800000000:
where convert(decimal(20,10), num) like '%68%'
When you are comparing number with LIKE it is implicitly converted to string and then matched
The problem here is that float number is not precise and when it is converted you can get
13457.679999999999999 instead of 13457.68
So to avid this explicitly format number in appropriate format(not sure how to do this in sql server, but it will be something like)
SELECT num FROM number_like_test
WHERE Format("0.##",num) LIKE '%68%'
The conversion to string is rounding your values. Both CONVERT and CAST have the same behavior.
SELECT cast(num as nvarchar(50)) as s
FROM number_like_test
Or
SELECT convert(nvarchar(50), num) as s
FROM number_like_test
provide the results:
1234.56
3457.68
13457.7
1234.76
23456.8
You'll have to use the STR function and correct format parameters to try to get your results. For example,
SELECT STR(num, 10, 2) as s
FROM number_like_test
gives:
1234.56
3457.68
13457.68
1234.76
23456.78
Pretty well solved already, but you only need to CAST once, not twice like the other answer suggests, LIKE takes care of the string conversion:
SELECT *
FROM number_like_test
WHERE CAST(num AS DECIMAL(12,6)) LIKE '%68%'
And here's a SQL Fiddle showing the rounding behavior: SQL Fiddle
It's probably because a FLOAT data type represents a floating point number which is an approximation of the number and should not be relied on for exact comparisons.
If you need to do a search that includes the float value you would need to either store it in a decimal data type (which will hold the exact number) or convert it to a varchar using something like the STR() function

sql int to decimal with no storage

I am currently writing in MS-SQL to convert old data to a new table and one of the variable in the old table is a int. In the new table it has to be a decimal(10,3) because of the data now being entered. The old data also has some nulls also. When I convert the data using round to generate the new decimal I get a error:
Msg 8115, Level 16, State 8, Line 1
Arithmetic overflow error converting int to data type numeric.
using the following code:
insert into Data_Exchange_Claims_History (Qty_Dispense)
select convert(decimal(10,3),round(ISNULL(Qty_Dispense, 0), 3))
from dbo.Data_Exchange_Claims_History_old c
I assume the question is how it can fail;
An INT won't always fit into a DECIMAL(10,3).
DECIMAL(10,3) means a total of 10 digits, of which 3 are to the right of the decimal point.
In other words, it can only represent integers up to 9999999.
An INT can fit into DECIMAL 10,3 only if it is <= 9,999,999
9,999,999 will turn into 9,999,999.000 (10 total digits, 3 decimals).
After playing with the problem for a while it dawned on me that I just needed to move the decimal over three places so I divided the numbers by 1000 and it worked. The new query looks like:
insert into Data_Exchange_Claims_History (Qty_Dispense)
select convert(decimal(10,3),(Qty_Dispense/1000))
from dbo.Data_Exchange_Claims_History_old c
Thanks to everyone who contributed to this as it helped me look at the problem in a new light.