I am getting the error 'Error converting data type nvarchar to float' when running the following
declare
#completeCommand nvarchar (max) = 'x'
,#paramVal nvarchar (100)
,#paramName nvarchar (100)
,#paramType nvarchar (100)
,#tempParam sql_variant
declare #parameterList table (
RowID int identity (1,1)
,ParameterValue nvarchar (100)
,ParameterName nvarchar (100)
,ParameterType nvarchar (100)
)
insert into #parameterList
values
('10', 'Param1', 'int')
,('test', 'Param2', 'nvarchar')
-- Process each parameter one at a time
declare ParameterCursor cursor fast_forward for
select ParameterValue, ParameterName, ParameterType
from #parameterList
order by RowID
open ParameterCursor
fetch next from ParameterCursor into #paramVal, #paramName, #paramType
if ##FETCH_STATUS = 0
set #completeCommand = #completeCommand + ' '
while ##FETCH_STATUS = 0
begin
print #completeCommand
-- verify the datatype is correct
set #tempParam = case #paramType
when 'int' then CAST (#paramVal as int)
when 'float' then CAST (#paramVal as float)
when 'nvarchar' then CAST (#paramVal as nvarchar)
else 'NULL'
end
set #completeCommand = #completeCommand + #paramName + ' = ' + #paramVal + ','
fetch next from ParameterCursor into #paramVal, #paramName, #paramType
end
close ParameterCurosr
deallocate ParameterCursor
What I am trying to do is verify that user entered data matches the expected data type before the data is added to a command string. Any feedback on why the above code fails would be greatly appreciated.
Cheers,
Joe
The issue is that CASE will return the data type with the highest precidence, of which is float for this statement. see CASE (Transact-SQL) and Data Type Precedence (Transact-SQL).
To get this CASE to work add a bogus WHEN 'xzy' then CAST (#paramVal as sql_variant) which will cause CASE to use sql_variant as the return data type.
OR remove the CASE and use IF-ELSE, like:
IF #paramType='int'
set #tempParam = CAST (#paramVal as int)
ELSE IF #paramType='float'
set #tempParam = CAST (#paramVal as float)
ELSE IF #paramType='nvarchar'
set #tempParam = CAST (#paramVal as nvarchar)
ELSE
set #tempParam = NULL
What you used was Simple Case function. Searched Case function should work (see below).
I've just tried it in a very simple query:
DECLARE #type VARCHAR(100)
DECLARE #input VARCHAR(100)
DECLARE #value SQL_VARIANT
SET #type = 'varchar'
SET #input = 'test'
SET #value = CASE
WHEN #type = 'varchar' THEN #input
WHEN #type = 'int' THEN CAST(#input AS VARCHAR)
END
On SQL Server 2005 I am getting the same error, but the following is from SQL Server 2008 doc:
Simple CASE function:
Evaluates input_expression, and then in the order specified, evaluates input_expression = when_expression for each WHEN clause.
Returns the result_expression of the first input_expression = when_expression that evaluates to TRUE.
If no input_expression = when_expression evaluates to TRUE, the SQL Server 2005 Database Engine returns the else_result_expression if an ELSE clause is specified, or a NULL value if no ELSE clause is specified.
Searched CASE function:
Evaluates, in the order specified, Boolean_expression for each WHEN clause.
Returns result_expression of the first Boolean_expression that evaluates to TRUE.
If no Boolean_expression evaluates to TRUE, the Database Engine returns the else_result_expression if an ELSE clause is specified, or a NULL value if no ELSE clause is specified.
If this is true, then Simple Case will do all the CASTS and then decide qhich one to use, while Searched Case will evaluate the boolean expression and then decide which CAST to execute. This should be the solution.
Otherwise, you can probably use IF ... THEN ... ELSE, as proposed in another answer.
Related
Consider the following TSQL code:
declare #a nvarchar(500) = N''
select try_convert(float, #a)
The output is:
0
I need the output to be NULL.
I can do this:
declare #a nvarchar(500) = N''
select case #a
when '' then null
else try_convert(float, #a)
end
and it works just fine.
However, this is just a mock-up. In my real life scenario, instead of #a, there are over 200 NVARCHAR(500) columns, either floats or zero length strings. I need a quick way of converting zero-length strings to NULL (and everything else to float), possibly without having to build 200 separate CASE statements.
I'm not really thrilled with relying the rather inexplicable differences between try_parse() and try_convert()/try_cast(). Instead, I would go for:
try_convert(float, nullif(#a, ''))
This also has the advantage of being quite explicit in what you are trying to accomplish.
You should use Try_parse instead
declare #a nvarchar(500) = N''
select try_parse( #a as float)
returns
NULL
See working demo
I have a column that contain these value from a table.
Colum1: dhd-29229 Table: Test
dhd-29199
dhd-00011
My goal is to write a select sql statement that will return the following value: All numeric value and not take into account dhd-
Use like:
where column1 like '%29229'
If you want exactly XXX-29199 in this format, you've to use :
where column1 like '___-29229'
If you want just the 29229, you can use : where column1 like '%29229' but in this case the query will return all values that ends with "29229". you can think to controle the length.
https://www.w3schools.com/sql/sql_like.asp
in T-SQL (sql server):
select substring(colum1, charindex('-',colum1)+1,5) as sub_string from test
If you want a strict 'numbers only' that does not reply upon format or inconsistencies... try writing a UDF :
Create FUNCTION [test].[numOnly]
(#text nvarchar (max))
RETURNS nvarchar (max)
AS
BEGIN
DECLARE
#char nvarchar(1),
#i_idx int,
#temp int,
#out nvarchar(max)
While len(#text) > 0
Begin
Set #char = left(#text,1)
if ascii(#char) between 49 and 57
set #out = isnull(#out,'') + #char
Set #text = RIGHT(#text,len(#text)-1)
End
Return #out
END
Use it thus ...
select [test].[numOnly]('44--(*)"*()£hllk564kkj3') as 'lala'
Result : 445643
SQL Code:
DECLARE #SortOrder nvarchar(max);
SET #SortOrder = 'name';
SELECT * FROM [database_name].[schema_name].[table_name]
ORDER BY CASE #SortOrder
WHEN 'id' THEN id
WHEN 'name' THEN name
END;
Output:
Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the nvarchar value 'foo' to data type int.
When I instead put #SortOrder = 'id', it works flawlessly. When I do a normal SELECT and ORDER BY name, it also works flawlessly.
Why would it try to convert that nvarchar value to data type int, and how can I stop it from doing so?
CASE is an expression that returns a single value of a specific data type. The potential values must be compatible, and since you must have a name value of foo, which can't be converted to INT, you get this error. The easiest way to solve this problem is to separate your ORDER BY expressions by data type:
ORDER BY CASE #SortOrder WHEN 'id' THEN id END,
CASE #SortOrder WHEN 'name' THEN name END;
Another alternative (which may be better for plan caching as long as you have optimize for ad hoc workloads on) would be dynamic SQL:
DECLARE #sql NVARCHAR(MAX) = N'SELECT ... ORDER BY ' + QUOTENAME(#SortOrder) + ';';
EXEC sp_executesql #sql;
Also not sure why you would give your #SortOrder a max data type - no column name could ever be anywhere near that large.
All routes through a case statement must output the same data type. Try casting the ID to a string like this and it will work.
DECLARE #SortOrder nvarchar(max);
SET #SortOrder = 'name';
SELECT * FROM [database_name].[schema_name].[table_name]
ORDER BY CASE #SortOrder
WHEN 'id' THEN cast(id AS NVARCHAR(20))
WHEN 'name' THEN name
END;
I am using SQL server 2008 R2 and Microsoft SQL Server Management Studio 0.50.2500.0.
In my Stored Procedure,
I am converting varchar to numeric(18,2).
select convert(numeric(18,2),' ')
It returned 0.00 when the value was ' ', which was required.
But now, its giving error 'Error converting data type varchar to numeric.'
Can anyone please tell me that what wrong I did ? or Which made this change?
Thanks in advance.
Dont know why but try this it should work investigate further why it will allow you to do this way and if you find anything on this do update us.
SELECT CONVERT(numeric(18,2),CAST(' ' AS INT))
Result
(No column name)
0.00
I have been looking online for some explanation only found this Link have a look still not very clear about this behaviour.
For,DECLARE #VAL1 float;
while executing this statement,
select convert(numeric(18,2),(case when 2=1 then #VAL1 else #VAL end ));
Sql server internally converts #VAL to Float(datatype of #VAL1) then compare gives you the output as zero.
DECLARE #VAL nvarchar(10);
DECLARE #VAL1 float;
set #VAL=' ';
set #VAL1=12.123;
select #VAL,#VAL1
select CONVERT(float,#VAL)--done by sql server internally
select convert(numeric(18,2),(case when 2=1 then #VAL1 else #VAL end ));
but,for DECLARE #VAL1 numeric(18,2)
it actually gets error at sql server internal conversion.
DECLARE #VAL nvarchar(10);
DECLARE #VAL1 numeric(18,2);
set #VAL=' ';
set #VAL1=12.123;
select #VAL,#VAL1
select CONVERT(numeric(18,2),#VAL)--at this point,sql sever unabled to convert #VAL to datatype Numeric
select convert(numeric(18,2),(case when 2=1 then #VAL1 else #VAL end ));
Not sure if you need it to also work with non-blank values
Declare #myValue varchar(10)
SET #myValue = ' '
SELECT
CASE
WHEN #myValue <> ' ' THEN
CONVERT(numeric(18,2), #myValue)
ELSE '0.00'
END
Outputs 0.00
Declare #myValue varchar(10)
SET #myValue = '3.2'
SELECT
CASE
WHEN #myValue <> ' ' THEN
CONVERT(numeric(18,2), #myValue)
ELSE
Outputs 3.20
http://blog.sqlauthority.com/2007/07/07/sql-server-convert-text-to-numbers-integer-cast-and-convert/
SELECT CAST(YourVarcharCol AS INT) FROM Table
SELECT CONVERT(INT, YourVarcharCol) FROM Table
Thanks All!!
I found the root cause. I have changed a column datatype float to numeric which related to the converted value.
Ex,
DECLARE #VAL nvarchar(10);
DECLARE #VAL1 float;
set #VAL=' ';
set #VAL1=12.123;
select convert(numeric(18,2),(case when 2=1 then #VAL1 else #VAL end ));
It Results
0.00
Changing #VAL1 datatype to numeric
DECLARE #VAL nvarchar(10);
DECLARE #VAL1 numeric(18,2);
set #VAL=' ';
set #VAL1=12.123;
select convert(numeric(18,2),(case when 2=1 then #VAL1 else #VAL end ));
It Results the error, 'Error converting data type nvarchar to numeric'.
Will be welcomed if anyone explain whats really happening here.
declare #value varchar(10)=''
select case when ISNUMERIC(#value)=1 then convert(numeric(18,2),#value) else convert(numeric(18,2),0) end
So if #value ='' result will be 0.00. also let say if value is 6 result will be 6.00
Hi please take a look and try this
declare #xx as varchar(10)
set #xx = ''
select case when #xx ='' then convert(numeric(18,2),'0.00')
else convert(numeric(18,2),#xx) end as test
Thanks
You can use TRY_CAST()
Syntax:
TRY_CAST ( expression AS data_type [ ( length ) ] )
Use TRY_PARSE ( string_value AS data_type [ USING culture ] )
in your case :
select TRY_PARSE(' ' as NUMERIC)
Remarks :
Use TRY_PARSE only for converting from string to date/time and number types. For general type conversions, continue to use CAST or CONVERT. Keep in mind that there is a certain performance overhead in parsing the string value.
TRY_PARSE relies on the presence of .the .NET Framework Common Language Runtime (CLR).
I have the following code to cast nvarchar to integer:
cast(#value as int)
However I have no control of the parameter #value, hence the code might fail. Is there anyway to check if a cast is possible before doing a cast?
Well, in SQL Server 2012 you could use the new TRY_CAST(), but with SQL Server 2008, you should be able to use ISNUMERIC(), and then include handling for values that do not pass that test.
I've recently answered a question about this and using ISNUMERIC to CAST to an INT won't work by itself. Reason being, ISNUMERIC returns true for non integer numbers (1.5) for example.
Here was a recent answer on the subject:
https://stackoverflow.com/a/14692165/1073631
Consider adding an additional check using CHARINDEX with ISNUMERIC, or what I prefer, use a Regular Expression to validate the data.
And here is a Fiddle demonstrating the problem with using ISNUMERIC on it's own. And the Fiddle using a regular expression instead that works.
DECLARE #Test nvarchar(10)
SET #Test = '1.5'
--Works
SELECT CASE WHEN #Test NOT LIKE '%[^0-9]%' THEN CAST(#Test as int) ELSE 0 END
-- Produces Error
SELECT CASE WHEN ISNUMERIC(#Test) = 1 THEN CAST(#Test as int) ELSE 0 END
Good luck.
I generally use the following, it seems to cover all the situations.
SELECT CASE WHEN 1 = ISNUMERIC(#value + '.0') THEN CAST(#value as int) ELSE 0 END
It takes advantage of the fact that "ISNUMERIC" will not allow two periods. The "TRY_CAST" in SQL Server 2012+ is a much better solution though.
The proper test is:
select (case when isnumeric(val) = 1 and val not like '%e%' and val not like '%.%'
then cast(val as int)
end)
The function isnumeric() returns 1 for anything that looks like a float, so you have to be careful.
You can also use what I consider to be a peculiarity of SQL Server. You can cast the floating value 1.23 to an int, but you cannot cast the string value. So, the following also works:
select (case when isnumeric(val) = 1
then cast(cast(val as float) as int)
end)
Maybe we can do something like this:
declare #value as nvarchar(10) = 'A';
begin try
select cast(#value as int);
end try
begin catch
-- do something
end catch
Use a procedure with a TRY CATCH block to suppress errors
i.e.
CREATE PROCEDURE p_try_cast
#type nvarchar(MAX),
#value nvarchar(MAX)
AS
BEGIN
BEGIN TRY
DECLARE #sql varchar(MAX)
DECLARE #out_table TABLE(value varchar(MAX))
SET #sql = 'SELECT CONVERT(varchar(max), CAST(''' + #value + ''' AS ' + #type + '))'
INSERT #out_table
EXECUTE (#sql)
IF EXISTS ( SELECT 1 FROM #out_table WHERE value = #value)
RETURN 1
RETURN 0
END TRY
BEGIN CATCH
RETURN 0
END CATCH
END
GO
Now you can call that with the passed string and desired type and the proc returns 1 for success and 0 for failure
DECLARE #ret int
-- This returns 0 - Fail
EXEC #ret = p_try_cast 'integer', '1.5'
-- This returns 1 - Success
EXEC #ret = p_try_cast 'integer', '1.5'
-- This returns 0 - Fail
EXEC #ret = p_try_cast 'char(4)', 'HELLO'
-- This returns 1 - Success
EXEC #ret = p_try_cast 'char(4)', 'HELL'