The reserve column is a varchar, to perform sums on it I want to cast it to a deciaml. But the SQL below gives me an error
select
cast(Reserve as decimal)
fr
Try (for example):
select
cast(Reserve as decimal(10,2))
from MyReserves
Numeric/Decimal generally want a precision an scale.
Use try_cast (sql 2012)
select
try_cast(Reserve as decimal)
from MyReserves
I am also facing this issue and I solved by below method. I am sharing this because it may helpful to some one.
declare @g varchar (50)
set @g=char(10)
select isnumeric(@g),@g, isnumeric(replace(replace(@g,char(13),char(10)),char(10),''))
It seems that isnumeric has some Problems:
http://www.sqlhacks.com/Retrieve/Isnumeric-problems (via internet archive)
According to that Link you can solve it like that:
select
cast(Reserve as decimal)
from MyReserves
where MyReserves is not null
and MyReserves * 1 = MyReserves
IsNumeric is a problem child -- SQL 2012 and later has TRY_CAST and TRY_CONVERT
If you're on an earlier version then you can write a function that'll convert to a decimal (or NULL if it won't convert). This uses the XML conversion functions that don't throw errors when the number won't fit ;)
-- Create function to convert a varchar to a decimal (returns null if it fails)
IF EXISTS( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID( N'[dbo].[ToDecimal]' ) AND type IN( N'FN',N'IF',N'TF',N'FS',N'FT' ))
DROP FUNCTION [dbo].[ToDecimal];
GO
CREATE FUNCTION ToDecimal
(
@Value VARCHAR(MAX)
)
RETURNS DECIMAL(18,8)
AS
BEGIN
-- Uses XML/XPath to convert @Value to Decimal because it returns NULL it doesn't cast correctly
DECLARE @ValueAsXml XML
SELECT @ValueAsXml = Col FROM (SELECT (SELECT @Value as Value FOR XMl RAW, ELEMENTS) AS Col) AS test
DECLARE @Result DECIMAL(38,10)
-- XML/XPath will return NULL if the VARCHAR can't be converted to a DECIMAL(38,10)
SET @Result = @ValueAsXml.value('(/row/Value)[1] cast as xs:decimal?', 'DECIMAL(38,10)')
RETURN CASE -- Check if the number is within the range for a DECIMAL(18,8)
WHEN @Result >= -999999999999999999.99999999 AND @Result <= 999999999999999999.99999999
THEN CONVERT(DECIMAL(18,8),@Result)
ELSE
NULL
END
END
Then just change your query to:
select dbo.ToDecimal(Reserve) from MyReserves
IsNumeric
is possibly not ideal in your scenario as from the highlighted Note on this MSDN page it says "ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($)."
Also there is a nice article here which further discusses ISNUMERIC
.