Problem convert column values from VARCHAR(n) to DECIMAL - sql-server

I have a SQL Server 2000 database with a column of type VARCHAR(255). All the data is either NULL, or numeric data with up to two points of precision (e.g. '11.85'). I tried to run the following T-SQL query but received the error 'Error converting data type varchar to numeric'
SELECT CAST([MyColumn] AS DECIMAL)
FROM [MyTable];
I tried a more specific cast, which also failed.
SELECT CAST([MyColumn] AS DECIMAL(6,2))
FROM [MyTable];
I also tried the following to see if any data is non-numeric, and the only values returned were NULL.
SELECT ISNUMERIC([MyColumn]), [MyColumn]
FROM [MyTable]
WHERE ISNUMERIC([MyColumn]) = 0;
I tried to convert to other data types, such as FLOAT and MONEY, but only MONEY was successful. So I tried the following:
SELECT CAST(CAST([MyColumn] AS MONEY) AS DECIMAL)
FROM [MyTable];
...which worked just fine. Any ideas why the original query failed? Will there be a problem if I first convert to MONEY and then to DECIMAL?
Thanks!

It's likely that this depends on whether the decimal symbol is a comma or a dot. Here are some test queries and their results:
select CAST('3.6' as decimal) -- 3.60
select CAST('3,6' as decimal) -- Error converting data type varchar to numeric.
select CAST('3.6' as money) -- 3.60
select CAST('3,6' as money) -- 36.00 (!)
select ISNUMERIC('3.6') -- 1
select ISNUMERIC('3,6') -- 1
The documentation for ISNUMERIC says :
ISNUMERIC returns 1 when the input
expression evaluates to a valid
integer, floating point number, money
or decimal type; otherwise it returns
0
Both 3.6 and 3,6 can be cast to money, so that's why isnumeric('3,6') returns 1.
To resolve this issue, replace the comma's with dots (or vice versa, if your system uses comma as the decimal symbol):
select cast(replace('3,6',',','.') as decimal)
Another option is to change the "decimal symbol" in Windows. It's in Config Panel -> Regional and Language -> Formats -> Additional Settings -> Numbers.

Another cause is empty strings. For example, if you use the import wizard to import a CSV file, empty fields will become empty strings, not nulls.
This is a common idiom for fixing this:
CAST(NULLIF([number_as_a_string],'') AS decimal(13,2))

Select CAST(isnull(MyColumn,0) as Decimal(4,2))
FROM [MyTable];

Related

Trying to convert NVARCHAR column value to DECIMAL(10,2)

I am getting this error when I'm trying to convert all nvarchar values in a specific column in my table and remove the $ from the value as well.
Here is the error:
Msg 8114, Level 16, State 5, Line 7
Error converting data type nvarchar to numeric.
Here is my code:
UPDATE dbo.CMS_BI_Demand
SET DemandAmount = (SELECT CONVERT(DECIMAL(10, 2), REPLACE(DemandAmount, '$', '')) as DemandAmt
FROM dbo.CMS_BI_Demand
WHERE BISysID = 1)
Any help/direction would be appreciated.
Here is my code that corrected the error:
UPDATE dbo.CMS_BI_Demand
SET DemandAmount = t1.DemandAmount
FROM (
SELECT BISysID, CONVERT(DECIMAL(10,2), REPLACE(REPLACE(DemandAmount,'$',''),',','')) as DemandAmount
FROM dbo.CMS_BI_Demand
) t1
WHERE dbo.CMS_BI_Demand.BISysID = t1.BISysID;
Are you sure the values are all numeric after replacing the $? I ran into this once and had to do some data cleanup before I could do the update. In my case, there was a space in one of the rows so it failed. As soon as I fixed the record, everything worked.
You didn't specify what sql you're running but if you're using Microsoft SQL, I would run a check using isnumeric and verify that nothing returns as false:
SELECT id, ISNUMERIC(REPLACE(DemandAmount,'$','')) as DemandAmt
FROM dbo.CMS_BI_Demand
WHERE BISysID = 1 AND ISNUMERIC(REPLACE(DemandAmount,'$','')) = 0
Different cultures have different decimal and thousand separators. When you call CONVERT the server will use the locale specified through the LANGUAGE setting to try and parse the string. At best, if the string and locale don't match, you'd get an error. The worst case is that the string will be passed using the wrong separator.
Given the $ symbol, it looks like you're trying to parse a US-style numeric string in a non-US locale. The solution is to use PARSE or TRY_PARSE with en-us as the culture :
select parse('234.5' as numeric(10,2) using 'en-us')
You can avoid trimming the currency sign if you parse to money first :
select parse('$234.5' as money using 'en-us')
DON'T try to replace separators. This can easily lead to wrong values and still fail to parse the text. What if the value was 2,345.123? Even if you remove the thousand separator, trying to convert this value eg in Germany would produce 2345123.00 :
select parse('2345.123' as decimal(10,2) using 'de-DE')
Returns :
2345123.00
You may assume this won't happen in production. How about the EUR/USD exchange rate? In Italy?
SELECT PARSE('1.12' as decimal(10,2) using 'it-IT')
------
112.00
Oops
To figure out what values your SQL SERVER instance can't properly cast to decimal(10,2), use this:
SELECT DemandAmount
FROM dbo.CMS_BI_Demand
WHERE TRY_CONVERT(DECIMAL(10,2), REPLACE(REPLACE(DemandAmount,'$',''),',','')) IS NULL

Error converting data type nvarchar to float in SQL Server 2008

select sum(cast(mmax as float)
from table
mmax is of datatype nvarchar and the value is
string,int,decimal, value
I trying to sum of like value 17.50,35.00.
I am avoiding string value in where clause
But not solved this problem
Error is thrown
String/Varchar values with commas such as "10,000" pass the IsNumeric() test but do not cast/convert into numeric types without raising an error.
You can replace the commas and perform the cast and sum operation:
select sum(cast(replace(mmax,',','') as float))
from tbl
where isnumeric(maxx)>0
One of the values cannot be converted to a float. You may have a million values that can convert if one (has a letter O instead of a 0 for example) you will get that message.

How to overcome limitation of ISNUMERIC column "ERROR : overflowed an int column"

I have a requirement wherein I have to check whether value entered in VARCHAR(200) column is numeric or not, and if so a relevant error message should be passed.
I am validating the same with ISNUMERIC function since my column value is varchar so user can enter more than 10 characters as well due to which I am getting this error:
overflowed an int column
Because of the other business support, I can not change the data type of the column to int.
As of now I have implemented LEN() < 10 condition before checking ISNUMERIC but seeking if any alternate and better option available.
If you work on Sql server 2012 Than its better to Use TRY_Convert() Function.it will give NULL as output rather than impose error
declare #d varchar(200)='940852774565564'
if ((select ISNUMERIC(#d))=1)
select Try_Convert(#d as bigint)
else
Convert the value to bigint rather than INT
declare #d varchar(200)='940852774565564'
if ((select ISNUMERIC(#d))=1)
select cast(#d as bigint)

SQL Server 2005 decimal field behaviour

Ive create a simple table with a field x of type decimal(28,15)
I run the following query to insert a value:
insert into testtable values (1234567890123)
when I do a select from testtable I, field x has a value of
1234567890123.000000000000000
Is there a way to specify (perhaps in the table design) that sql server should NOT store the zero's after the decimal if its not required? i.e. when doing a select the data will be returned as
1234567890123
Also why does insert into testtable values (12345678901234) give the following error :
Arithmetic overflow error converting numeric to data type numeric.
Also why does insert into testtable values (12345678901234) give the following error :
You specified a total width of 28 with 15 digits after decimal point. That leaves at most 13 digits before decimal point.
Is there a way to specify that sql server should NOT store the zero's after the decimal if its no required?
Strictly speaking, "decimal" is a fixed precision format and thus any number will occupy exactly the same space as any other number (see MSDN).
Try the below query . it works fine ...
select cast(1234567890123.000000000000000 as decimal)

What is the data type of "select 123.866" in SQL server 2005?

If I just write something like
select 10.00;
What type does this give me?
Here's a test I ran, to test the binary representation of these types. The big surprise here is that none of the casts actually match the first row!
select cast(123.866 as binary) union all
select cast(cast(123.866 as real) as binary) union all
select cast(cast(123.866 as float) as binary) union all
select cast(cast(123.866 as decimal) as binary) union all
select cast(cast(123.866 as numeric) as binary) union all
select cast(cast(123.866 as money) as binary) union all
select cast(cast(123.866 as smallmoney) as binary)
--------------
0x0000000000000000000000000000000000000000000006030001DAE30100
0x000000000000000000000000000000000000000000000000000042F7BB64
0x00000000000000000000000000000000000000000000405EF76C8B439581
0x00000000000000000000000000000000000000000000120000017C000000
0x00000000000000000000000000000000000000000000120000017C000000
0x00000000000000000000000000000000000000000000000000000012E684
0x00000000000000000000000000000000000000000000000000000012E684
Can anyone explain this?
Originally, all I wanted to do was avoid having to write the cast statement, assuming 123.866 was implicitly a decimal. So I thought to test if these two statements were the same:
select cast(123.866 as decimal)
select 123.866
In addition to #David M's answer, here's a way to find the type directly, found here: less than dot: How to implement a typeof operator in SQL by using sql_variant_property:
select
CAST(SQL_VARIANT_PROPERTY(123.866, 'BaseType') AS VARCHAR(20)) AS Type,
CAST(SQL_VARIANT_PROPERTY(123.866, 'Precision') AS INT) AS Precision,
CAST(SQL_VARIANT_PROPERTY(123.866, 'Scale') AS INT) AS Scale
Which gives me this answer:
Type Precision Type
numeric 6 3
Note that I tested this on SQL Server 2008, not 2005. I hope that function is available in 2005.
numeric is further described here: Data Types (Transact SQL), and here: decimal and numeric (Transact-SQL).
It's implicitly typed as decimal(6,3) - cast to this and you'll see the binary values match. It seems to use decimal at the smallest tpe to fit the value - in this case, 6 digits including 3 after the decimal place.
In your test, you are using union all. Did you know that all values will be cast to the same data type in a union query?
SQL Server Precision and Scale problems
This article also demonstrates what happens when you combine various data types together.
Are you sure you have to cast it in your query? When you select the result, what's next in line to process it? If it's an application, have the code properly determine and cast the type (if needed). If it's another query, you may be able to pass it along without any issues.

Resources