Getting an error converting varchar to float.
Have a table (not of my making) with column result
, having varchar data. I\'d like to convert to float to
It means you have at least one row in the table that cannot be cast to float
. Doing the CASE
is safe, but combining the CTE and adding a WHERE clause falls into a common fallacy of programmers when writing T-SQL: that order of declaration implies an order of execution. Programmers are used to the imperative procedural style of C like languages and fail to comprehend the declarative set based nature of SQL. I have wrote before about this issue and gave examples when the fallacy causes errors:
Once you post your full code we can see where exactly did you make the fallacy in your case and assumed a certain order of execution.
after update
OK, so I have to admin that in your case the code is correct in the order of execution, the result
column cannot be projected w/o first evaluating the CASE
. Had the CASE been in a WHERE clause things would have been different.
Your problem is different: ISNUMERIC. This function has a very generous understanding of what NUMERIC
means and has bitten many developers before. Namely, it accepts values that CAST and CONVERT will reject. Like ones containing a comma:
declare @n varchar(8000) = '1,000';
select isnumeric(@n);
select cast(@n as float);
select case when isnumeric(@n)=1 then cast(@n as float) else null end;
So you have values that pass the ISNUMERIC
test but fail to convert. Just a heads up, the more you'll digg into this approach, the more closed doors you'll find. Is just no safe way to do the cast you need on the server side. Ideally, fix the data model (make the field a float if it stores floats). Short of that, triage the data and remove all values that are not a proper float, and fix the front-end/application to no longer introduce new ones, then add a constraint that will trigger the error if new bad values appear. You won't be able to solve this in a query, that road is littered with bodies.
With the next version of SQL Server you will have a new function, TRY_CONVERT, that would solve your problem.
Simply an explicit conversion but with a little ingenuity the REPLACE
SELECT result FROM table WHERE CONVERT(float,REPLACE(result,',','.')) > 180.0
Check this out:
http://classicasp.aspfaq.com/general/what-is-wrong-with-isnumeric.html
Basically, there are some known issues / oddities with the ISNUMERIC function. The author of that article suggests creating a new function and using that instead of ISNUMERIC. I tested it with the 1,0
value you suggested and it seems to work.
CREATE FUNCTION dbo.isReallyNumeric
(
@num VARCHAR(64)
)
RETURNS BIT
BEGIN
IF LEFT(@num, 1) = '-'
SET @num = SUBSTRING(@num, 2, LEN(@num))
DECLARE @pos TINYINT
SET @pos = 1 + LEN(@num) - CHARINDEX('.', REVERSE(@num))
RETURN CASE
WHEN PATINDEX('%[^0-9.-]%', @num) = 0
AND @num NOT IN ('.', '-', '+', '^')
AND LEN(@num)>0
AND @num NOT LIKE '%-%'
AND
(
((@pos = LEN(@num)+1)
OR @pos = CHARINDEX('.', @num))
)
THEN
1
ELSE
0
END
END
GO