Empty string should be NULL when converting to float - sql

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

Related

using user variable in 'IN' clause of sql

declare #A varchar(5000)
declare #B varchar(5000)
select #A=value from drp.Parameter where parameteridname='IV01'
--result of this query ('DIM003966','DIM000736','DIM025297',
-- 'DIM025302','DIM027583')
select [InventLocationId],[WMSLocationId] from ItemKit.InventDim
where inventdimid in (#A)
i am not getting any result out of second query but if i run them individually and use result of 1st query in second i am getting it. is there any way around to run them together
That is because it evaluates #a as is (as text, not a list of values).
You should create a sql statement on the fly and execute it:
declare #sqlStatement nvarchar(4000)
#sqlStatement = 'select [InventLocationId],[WMSLocationId] from ItemKit.InventDim where inventdimid in (' + #A + ')'
execute sp_executesql #sqlStatement
But as said by others, don't use unless really necessary.
You should use this code:
select [InventLocationId],[WMSLocationId] from ItemKit.InventDim
where inventdimid in (select value from drp.Parameter where parameteridname='IV01')
As you have a single string value (holding all the values) you could either:
Parse sql on the fly
Note: I do not recommend this, as it can allow sql injection
(see #Patrick Hofman's answer for good example of this)
Use like
declare #A varchar(5000)
declare #B varchar(5000)
select #A=value from drp.Parameter where parameteridname='IV01'
--result of this query ('DIM003966','DIM000736','DIM025297',
-- 'DIM025302','DIM027583')
SELECT #A /* Here you will see the problem, as it is not multiple values,
it is a single string with a comma & quote (') delimited list */
SELECT
[InventLocationId], [WMSLocationId]
FROM
ItemKit.InventDim
WHERE
/* parse up the inventdimid to include the quote (') around it */
#A like '%''' + #inventdimid + '''%'

Converting empty varchar to numeric

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).

sql server - check to see if cast is possible

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'

Cannot cast nvarchar to float

I have a weird problem.
In my query I select 5 columns which two of them are nvarchar in the form of numeric (only contains number and precision point), and other three are uniqueIdentifier and nvarchar.
I want to cast these two columns to Float in my select statement but I'm getting an error
Cannot cast nvarchar to float.
I checked the format of all these values many many times. Trust me, they are fine.
But when I just select these two columns and cast them to float the query runs successfully.
I appreciate any help on this subject.
I can paste the query here too. but the whole query is more then 100 lines and this will be frustrating to write and read!
Definitely going to need more info from you before answering. Can you post some of your code (or a small reproduction of your issue)? Perhaps your table definition as well?
Since all of the values are numeric, why leave the column as an nvarchar?
Finally, does any of your data contain a dollar sign ($)?
This works:
DECLARE #Text nvarchar(100)
SET #Text = '1234.567'
SELECT CONVERT(float, #Text) AS ColumnValue
So does this:
DECLARE #Text nvarchar(100)
SET #Text = ' 1234.567 '
SELECT CONVERT(float, #Text) AS ColumnValue
But this does not:
DECLARE #Text nvarchar(100)
SET #Text = '$1234.567'
SELECT CONVERT(float, #Text) AS ColumnValue
Not sure without seeing your query, but I think this should work:
SELECT CONVERT(Float(2), LTRIM(RTRIM(<nVarchar Column>))) AS Amount FROM ......

SQL Server: How do you remove punctuation from a field?

Any one know a good way to remove punctuation from a field in SQL Server?
I'm thinking
UPDATE tblMyTable SET FieldName = REPLACE(REPLACE(REPLACE(FieldName,',',''),'.',''),'''' ,'')
but it seems a bit tedious when I intend on removing a large number of different characters for example: !##$%^&*()<>:"
Thanks in advance
Ideally, you would do this in an application language such as C# + LINQ as mentioned above.
If you wanted to do it purely in T-SQL though, one way make things neater would be to firstly create a table that held all the punctuation you wanted to removed.
CREATE TABLE Punctuation
(
Symbol VARCHAR(1) NOT NULL
)
INSERT INTO Punctuation (Symbol) VALUES('''')
INSERT INTO Punctuation (Symbol) VALUES('-')
INSERT INTO Punctuation (Symbol) VALUES('.')
Next, you could create a function in SQL to remove all the punctuation symbols from an input string.
CREATE FUNCTION dbo.fn_RemovePunctuation
(
#InputString VARCHAR(500)
)
RETURNS VARCHAR(500)
AS
BEGIN
SELECT
#InputString = REPLACE(#InputString, P.Symbol, '')
FROM
Punctuation P
RETURN #InputString
END
GO
Then you can just call the function in your UPDATE statement
UPDATE tblMyTable SET FieldName = dbo.fn_RemovePunctuation(FieldName)
I wanted to avoid creating a table and wanted to remove everything except letters and digits.
DECLARE #p int
DECLARE #Result Varchar(250)
DECLARE #BadChars Varchar(12)
SELECT #BadChars = '%[^a-z0-9]%'
-- to leave spaces - SELECT #BadChars = '%[^a-z0-9] %'
SET #Result = #InStr
SET #P =PatIndex(#BadChars,#Result)
WHILE #p > 0 BEGIN
SELECT #Result = Left(#Result,#p-1) + Substring(#Result,#p+1,250)
SET #P =PatIndex(#BadChars,#Result)
END
I am proposing 2 solutions
Solution 1: Make a noise table and replace the noises with blank spaces
e.g.
DECLARE #String VARCHAR(MAX)
DECLARE #Noise TABLE(Noise VARCHAR(100),ReplaceChars VARCHAR(10))
SET #String = 'hello! how * > are % u (: . I am ok :). Oh nice!'
INSERT INTO #Noise(Noise,ReplaceChars)
SELECT '!',SPACE(1) UNION ALL SELECT '#',SPACE(1) UNION ALL
SELECT '#',SPACE(1) UNION ALL SELECT '$',SPACE(1) UNION ALL
SELECT '%',SPACE(1) UNION ALL SELECT '^',SPACE(1) UNION ALL
SELECT '&',SPACE(1) UNION ALL SELECT '*',SPACE(1) UNION ALL
SELECT '(',SPACE(1) UNION ALL SELECT ')',SPACE(1) UNION ALL
SELECT '{',SPACE(1) UNION ALL SELECT '}',SPACE(1) UNION ALL
SELECT '<',SPACE(1) UNION ALL SELECT '>',SPACE(1) UNION ALL
SELECT ':',SPACE(1)
SELECT #String = REPLACE(#String, Noise, ReplaceChars) FROM #Noise
SELECT #String Data
Solution 2: With a number table
DECLARE #String VARCHAR(MAX)
SET #String = 'hello! & how * > are % u (: . I am ok :). Oh nice!'
;with numbercte as
(
select 1 as rn
union all
select rn+1 from numbercte where rn<LEN(#String)
)
select REPLACE(FilteredData,' ',SPACE(1)) Data from
(select SUBSTRING(#String,rn,1)
from numbercte
where SUBSTRING(#String,rn,1) not in('!','*','>','<','%','(',')',':','!','&','#','#','$')
for xml path(''))X(FilteredData)
Output(Both the cases)
Data
hello how are u . I am ok . Oh nice
Note- I have just put some of the noises. You may need to put the noises that u need.
Hope this helps
You can use regular expressions in SQL Server - here is an article based on SQL 2005:
http://msdn.microsoft.com/en-us/magazine/cc163473.aspx
I'd wrap it in a simple scalar UDF so all string cleaning is in one place if it's needed again.
Then you can use it on INSERT too...
I took Ken MC's solution and made it into an function which can replace all punctuation with a given string:
----------------------------------------------------------------------------------------------------------------
-- This function replaces all punctuation in the given string with the "replaceWith" string
----------------------------------------------------------------------------------------------------------------
IF object_id('[dbo].[fnReplacePunctuation]') IS NOT NULL
BEGIN
DROP FUNCTION [dbo].[fnReplacePunctuation];
END;
GO
CREATE FUNCTION [dbo].[fnReplacePunctuation] (#string NVARCHAR(MAX), #replaceWith NVARCHAR(max))
RETURNS NVARCHAR(MAX)
BEGIN
DECLARE #Result Varchar(max) = #string;
DECLARE #BadChars Varchar(12) = '%[^a-z0-9]%'; -- to leave spaces - SELECT #BadChars = '%[^a-z0-9] %'
DECLARE #p int = PatIndex(#BadChars,#Result);
DECLARE #searchFrom INT;
DECLARE #indexOfPunct INT = #p;
WHILE #indexOfPunct > 0 BEGIN
SET #searchFrom = LEN(#Result) - #p;
SET #Result = Left(#Result, #p-1) + #replaceWith + Substring(#Result, #p+1,LEN(#Result));
SET #IndexOfPunct = PatIndex(#BadChars, substring(#Result, (LEN(#Result) - #SearchFrom)+1, LEN(#Result)));
SET #p = (LEN(#Result) - #searchFrom) + #indexOfPunct;
END
RETURN #Result;
END;
GO
-- example:
SELECT dbo.fnReplacePunctuation('This is, only, a tést-really..', '');
Output:
Thisisonlyatéstreally
If it's a one-off thing, I would use a C# + LINQ snippet in LINQPad to do the job with regular expressions.
It is quick and easy and you don't have to go through the process of setting up a CLR stored procedure and then cleaning up after yourself.
Can't you use PATINDEX to only include NUMBERS and LETTERS instead of trying to guess what punctuation might be in the field? (Not trying to be snarky, if I had the code ready, I'd share it...but this is what I'm looking for).
Seems like you need to create a custom function in order to avoid a giant list of replace functions in your queries - here's a good example:
http://www.codeproject.com/KB/database/SQLPhoneNumbersPart_2.aspx?display=Print