Varchar to Numeric conversion - CLR or 'e0' - sql

I want to convert data from Varchar column to Numeric data type -
so before conversion I am calling ISNUMERIC function to check whether data is numeric and if yes convert it to numeric data type. But I am facing an issue -
IsNumeric function is not behaving as expected -
- IsNumeric(x) returns true - when varchar value has both comma and a tab character (Char(9)),
- IsNumeric(x) returns false - when varchar value has only tab character and no comma
It is explained with the help of below SQL -
DECLARE #propValue AS VARCHAR(50)
SET #propValue = '1,592 ' -- contains comma + tab (Char(9))
SELECT ISNUMERIC(#propValue) -- Returns 1
--If ISNUMERIC func returns true for this value, lets convert this Varchar value to Numeric
SELECT CAST(#propValue AS Numeric(19, 4)) -- :-( Error converting data type varchar to numeric.
I Googled and found various solutions to tackle this problem -
--Solution 1: use 'e0'
SELECT ISNUMERIC(#propValue + 'e0') -- Returns 0
--Solution 2: remove comma before calling IsNumeric()
SELECT ISNUMERIC(REPLACE(#propValue, ',', '')) -- Returns 0
--Solution 3
--Call CLR function to parse Varchar value
What is the recommended solution in above scenario and why?
Also, I would really appreciate if anyone can explain why IsNumeric(x) returns false - when varchar value has only tab character and no comma?
Thank you!

Keep in mind that ISNUMERIC() = 1 does not mean "can be converted to every numeric type" but rather "can be converted to at least one numeric type." This comes up a lot where the value can be converted to at least one numeric type, but not the one you want. A much more basic example:
IF ISNUMERIC(256) = 1
SELECT CONVERT(TINYINT, 256);
If you have strings that have known violations (such as tabs), then why not also replace tabs? Why not prevent garbage data from getting into this value in the first place?
This works but it is quite ugly:
DECLARE #x TABLE (propValue VARCHAR(50));
INSERT #x SELECT '1,592' + CHAR(9)
UNION ALL SELECT '55' + CHAR(9) + '32'
UNION ALL SELECT CHAR(9) + '7,452.32 '
UNION ALL SELECT 'foo'
UNION ALL SELECT '74';
SELECT CONVERT(NUMERIC(19,4),
LTRIM(RTRIM(REPLACE(REPLACE(propValue, CHAR(9), ''), ',', '')))
)
FROM #x
WHERE ISNUMERIC(LTRIM(RTRIM(REPLACE(REPLACE(propValue,
CHAR(9), ''), ',', ''))) + 'e0') = 1;
While not applicable to your exact question, I wrote a FAQ about this 10 years ago: http://classicasp.aspfaq.com/general/what-is-wrong-with-isnumeric.html

ISNUMERIC(RTRIM(LTRIM(x))) = 1

Related

Error converting varchar value to data type int

I am trying to concatenate two integer values with hyphen in between. So when I try to do the same, SQL gives me the error.
Conversion failed when converting the varchar value '30-45' to data type int.
NOTE:
Also, the second value for concatenation can be null so in that case, a hyphen should not be concatenated.
example
from1 = 30
to1 = 45
case
to1 is null
then from1
else CONCAT(from1, '-' + nullif(to1,'')) end
AS age
//This works but shows 3045 instead of 30-45.
concat(from, '-', to) AS age
//This doesn't work out as it gives the error 'Conversion failed when converting the varchar value '30-45' to data type int.'
Thanks for the help in advance and looking forward to it.
DECLARE #FROM INT=30;
DECLARE #TO INT=45;
SELECT CAST(#FROM AS VARCHAR(2))+'-'+CAST(ISNULL(#TO,'') AS VARCHAR(2));
SQL is trying to convert your phrase to int probably because it's part of CASE statement. It uses the first route to determine the output type.
In your case- you put NULL as the first route option in your CASE, so it is determined as int. try putting instead of it this: CAST(NULL AS VARCHAR(10))
It seems that for some reason you think that strings that contain mathematical expressions are resolved as said expression, not an as literal string. Thus if you have the varchar value '30-45' you think it'll return the int value -15; this isn't true. This in fact isn't true in any language, let alone T-SQL.
For what you have, in your ELSE the '-' isn't a minus... It's a string... - is a minus. If you want to substract a number from another then it's a basic maths expression: a - b. You're effectively doing CONVERT(varchar,a) + '-' + CONVERT(varchar,b)... Just have your ELSE as the following:
from1 - NULLIF(to1,0)
This will return NULL if from1 has the value NULL, or to1 has the value NULL or 0.
Please check below code. It's working
example
#from1 = 30
#to1 = 45
IF #to1 is null
SELECT #from1
ELSE
SELECT CONCAT(#from1, '-' , nullif(#to1,'')) as age

Concatenate and add a character to integer columns in SQL

I have a 10 Character length values in a column in SQL Server. I need to split that column at fixed length and remove the leading zeros and add a - after each of the values.
I am able to split the values by using Substring and converting them to int. It is working well.
However, when I try to concatenate it is failing. Appreciate if you can help.
SELECT TOP 1 R.COL1, CAST(SUBSTRING(R.COL1,1,1) AS int) AS F1,CAST(SUBSTRING(R.COL1,2,5) AS int) AS F2,CAST(SUBSTRING(R.COL1,7,4) AS int) AS F3 CAST(SUBSTRING(R.COL1,1,1) AS int) +'-' +CAST(SUBSTRING(R.COL1,2,5) AS int) +'-' + CAST(SUBSTRING(R.COL1,7,4) AS int) AS finalString FROM MYTABLE R
If the value for COL1 IS 1012950001 the finalString I am expecting is 1-1295-1
however the result I am getting from the above query is 1297 as it is adding all the values.
Appreciate if you can help.
You can't use the + operator with a numerical data type and a varchar that cannot implicitly be converted to that data type. Something like 1 + 'a' isn't going to work, as 'a' isn't an int, and can't be implicitly converted to one.
If you are mixing data types, then use CONCAT, which implicitly converts each part into a (n)varchar:
CONCAT({Numerical Expression},'a',{Other varchar Expression})
You can use concat method to concatenate the substring value
select
concat(CAST(SUBSTRING('1012950001',1,1) AS int), '-',
CAST(SUBSTRING('1012950001',2,5) AS int), '-',
CAST(SUBSTRING('1012950001',7,4) AS int)) AS finalString
This will give you the expected result '1-1295-1'

Need to pad zeros left and right for a string value according to decimal format

So if I have a data (varchar) like say 10.1
I need the value as 0000101000000.
means (000010) whole number and (1000000) decimal value.
Its a 13 character string ,numbers coming before decimal point should be in first 6 characters and numbers coming after decimal point should be in last 7 characters
Maybe..?
DECLARE #d decimal(13,7) = 10.1;
SELECT RIGHT('0000000000000' + CONVERT(varchar(13),CONVERT(bigint,(#d * 10000000))),13);
Using my crystal ball here though.
Edit: As, for some reason, the OP is storing a decimal as a varchar (this is a really bad bad idea on it's own), I have added further logic to attempt to convert the value to a decimal first.
As experience has taught many of us, give a user a non-numeric column to store a numeric value in and they're more than happily store a non-numeric value in it, so i have used TRY_CONVERT and assumed you are using SQL Server 2012+:
DECLARE #d varchar(13) = 10.1;
SELECT RIGHT('0000000000000' + CONVERT(varchar(13),CONVERT(bigint,(TRY_CONVERT(decimal(13,7),#d) * 10000000))),13);
SELECT REPLICATE('0',6-LEN(SUBSTRING(CAST([data] AS VARCHAR), 1,
CHARINDEX('.',CAST([data] AS VARCHAR)) -1)))+SUBSTRING(CAST([data] AS VARCHAR), 1,
CHARINDEX('.',CAST([data] AS VARCHAR)) -1)+
SUBSTRING(CAST([data] AS VARCHAR), CHARINDEX('.',CAST([data] AS VARCHAR)) + 1,
LEN(CAST([data] AS VARCHAR)))+REPLICATE('0',7-LEN(SUBSTRING(CAST([data] AS VARCHAR), CHARINDEX('.',CAST([data] AS VARCHAR)) + 1,
LEN(CAST([data] AS VARCHAR))))) AS Whole
FROM Table1
Output
Whole
0000101000000
Demo
http://sqlfiddle.com/#!18/8649d/16
You can use some math and string operations to do it like below
see live demo
declare #var decimal(10,4)
set #var=10.1
select #var,
right(cast(cast(( floor(#var)+ power(10,7)) as int) as varchar(13)),6)
+
cast(cast(((#var- floor(#var)) * power(10,7)) as int) as varchar(13))
There's a fair amount of string manipulation to be done here. I'll step through what I did.
I used a variable for the base number so I could verify different results:
declare #n decimal(9,3) = 10.1
You need 6 spaces left of the decimal and 7 spaces to the right, so I'm doing all the manipulation on a VARCHAR(13). I didn't create a new variable as a VARCHAR because I'm assuming you want to be able to do this conversion in line on the fly, so I'm using that CAST over and over again.
Start by finding the decimal place.
SELECT CHARINDEX('.',CAST(#n as VARCHAR(13)))
In the sample number, that's a 3, but it could obviously change.
Now, get the portion of the number to the left of the decimal place.
SELECT SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1)
Then get the portion to the right of the decimal.
SELECT SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13))))
Pad the leading zeroes. Put 6 on, concatenate, and take a RIGHT 6. Accounts for no digits to the left of the decimal.
SELECT RIGHT(REPLICATE(0,6) + SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1), 6)
Pad the trailing zeroes. Same idea, but in the other direction.
SELECT LEFT(SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13)))) + REPLICATE(0,7),7)
Then put it all together.
SELECT RIGHT(REPLICATE(0,6) + SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1), 6)
+
LEFT(SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13)))) + REPLICATE(0,7),7)
Results.
0000101000000
declare #var varchar(20) = '10000.112'
SELECT FORMAT (FLOOR(#var), '000000') + left((PARSENAME(#var,1)) + replicate('0',7),7)

How to convert Varchar to Int in sql server 2008?

How to convert Varchar to Int in sql server 2008.
i have following code when i tried to run it wont allowed me to convert Varchar to Int.
Select Cast([Column1] as INT)
Column1 is of Varchar(21) NOT NULL type and i wanted to convert it into Int.
actually i am trying to insert Column1 into another table having Field as INT.
can someone please help me to convert this ?
Spaces will not be a problem for cast, however characters like TAB, CR or LF will appear as spaces, will not be trimmed by LTRIM or RTRIM, and will be a problem.
For example try the following:
declare #v1 varchar(21) = '66',
#v2 varchar(21) = ' 66 ',
#v3 varchar(21) = '66' + char(13) + char(10),
#v4 varchar(21) = char(9) + '66'
select cast(#v1 as int) -- ok
select cast(#v2 as int) -- ok
select cast(#v3 as int) -- error
select cast(#v4 as int) -- error
Check your input for these characters and if you find them, use REPLACE to clean up your data.
Per your comment, you can use REPLACE as part of your cast:
select cast(replace(replace(#v3, char(13), ''), char(10), '') as int)
If this is something that will be happening often, it would be better to clean up the data and modify the way the table is populated to remove the CR and LF before it is entered.
you can use convert function :
Select convert(int,[Column1])
That is how you would do it, is it throwing an error? Are you sure the value you are trying to convert is convertible? For obvious reasons you cannot convert abc123 to an int.
UPDATE
Based on your comments I would remove any spaces that are in the values you are trying to convert.
That is the correct way to convert it to an INT as long as you don't have any alpha characters or NULL values.
If you have any NULL values, use
ISNULL(column1, 0)
Try the following code. In most case, it is caused by the comma issue.
cast(replace([FIELD NAME],',','') as float)
Try with below command, and it will ask all values to INT
select case when isnumeric(YourColumn + '.0e0') = 1
then cast(YourColumn as int)
else NULL
end /* case */
from YourTable
There are two type of convert method in SQL.
CAST and CONVERT have similar functionality. CONVERT is specific to SQL Server, and allows for a greater breadth of flexibility when converting between date and time values, fractional numbers, and monetary signifiers. CAST is the more ANSI-standard of the two functions.
Using Convert
Select convert(int,[Column1])
Using Cast
Select cast([Column1] as int)

cast or convert a float to nvarchar?

I need to select from one column of datatype float and insert it in another column as nvarchar.
I tried to cast it: cast([Column_Name] as nvarchar(50))
The result was 9.07235e+009 instead of a 10 digit number (phone number).
Does any one know how to cast or convert this data properly?
Check STR. You need something like SELECT STR([Column_Name],10,0) ** This is SQL Server solution, for other servers check their docs.
If you're storing phone numbers in a float typed column (which is a bad idea) then they are presumably all integers and could be cast to int before casting to nvarchar.
So instead of:
select cast(cast(1234567890 as float) as nvarchar(50))
1.23457e+009
You would use:
select cast(cast(cast(1234567890 as float) as int) as nvarchar(50))
1234567890
In these examples the innermost cast(1234567890 as float) is used in place of selecting a value from the appropriate column.
I really recommend that you not store phone numbers in floats though!
What if the phone number starts with a zero?
select cast(0100884555 as float)
100884555
Whoops! We just stored an incorrect phone number...
Do not use floats to store fixed-point, accuracy-required data.
This example shows how to convert a float to NVARCHAR(50) properly, while also showing why it is a bad idea to use floats for precision data.
create table #f ([Column_Name] float)
insert #f select 9072351234
insert #f select 907235123400000000000
select
cast([Column_Name] as nvarchar(50)),
--cast([Column_Name] as int), Arithmetic overflow
--cast([Column_Name] as bigint), Arithmetic overflow
CAST(LTRIM(STR([Column_Name],50)) AS NVARCHAR(50))
from #f
Output
9.07235e+009 9072351234
9.07235e+020 907235123400000010000
You may notice that the 2nd output ends with '10000' even though the data we tried to store in the table ends with '00000'. It is because float datatype has a fixed number of significant figures supported, which doesn't extend that far.
For anyone willing to try a different method, they can use this:
select FORMAT([Column_Name], '') from YourTable
This will easily change any float value to nvarchar.
Float won't convert into NVARCHAR directly, first we need to convert float into money datatype and then convert into NVARCHAR, see the examples below.
Example1
SELECT CAST(CAST(1234567890.1234 AS FLOAT) AS NVARCHAR(100))
output
1.23457e+009
Example2
SELECT CAST(CAST(CAST(1234567890.1234 AS FLOAT) AS MONEY) AS NVARCHAR(100))
output
1234567890.12
In Example2 value is converted into float to NVARCHAR
You can also do something:
SELECT CAST(CAST(34512367.392 AS decimal(30,9)) AS NVARCHAR(100))
Output:
34512367.392000000
I had same problem and i saw your solution.
Good solution, its worked, thank you...
I created a function with your codes. Now i use it.
My function is here:
create function dbo.fnc_BigNumbertoNvarchar (#MyFloat float)
returns NVARCHAR(50)
AS
BEGIN
RETURN REPLACE (RTRIM (REPLACE (REPLACE (RTRIM ((REPLACE (CAST (CAST (#MyFloat AS DECIMAL (38 ,18 )) AS VARCHAR( max)), '0' , ' '))), ' ' , '0'), '.', ' ')), ' ','.')
END
Continuing a1ex07's answer - to use STR function (SQL SERVER),
and Ronen Festinger's comment - that he gets asterisks instead of digits,
I wanted to point out that the default length of STR is 10,
therefore, for large numbers, don't forget to use the length argument
For example: STR(1234567890123, 14)
DECLARE #MyFloat [float]
SET #MyFloat = 1000109360.050
SELECT REPLACE (RTRIM (REPLACE (REPLACE (RTRIM ((REPLACE (CAST (CAST (#MyFloat AS DECIMAL (38 ,18 )) AS VARCHAR( max)), '0' , ' '))), ' ' , '0'), '.', ' ')), ' ','.')