How to safely convert a varchar(255) to an int? - sql

I was using a column in a case expression and it was working fine on server1. When I ran it on server2 it was failing because the column had the value 'false' in it.
The column is a varchar(255), but in my case expression I was using it as if it was an INT type. It worked fine but now it is failing because of the 'false' value in server2.
How can I safely convert to an INT, and if the conversion fails, default to 0.
Is this possible?
My query looks like:
UPDATE t1
set
c1 = ISNULL(
(
SELECT CASE c2
WHEN 123 then 'hello'
WHEN 234 then 'bye'
ELSE ''
END
)
, '')
FROM table1 as t1

There are quite a few ways to convert from numeric to varchar, but none of them are available to you (really, SQLServer2008 is disappointing because it's lacking just a few cool features that are nearly required).
In your case, the best way to do is it simply to convert your numeric expression to varchar like this :
UPDATE t1
set c1 = CASE c2
WHEN '123' then 'hello'
WHEN '234' then 'bye'
ELSE ''
END
FROM #t1 t1
It doesn't answer the question, but it solves your problem.

Use TRY_PARSE (SQL Server 2012+):
SELECT ISNULL(TRY_PARSE(column_name AS INT),0)
FROM your_table;
LiveDemo

Related

SQL case statement then convert to int

I have a field that I want to convert to int so I can to a count, however some of the field's values are 'null' so I'm getting an exception when it comes across these
Conversion failed when converting the nvarchar value '_____' to data type int.
I thought id be able to do something like the below but I get the same result.
CAST( CASE [value] WHEN 'is null' THEN 1 ELSE [value] END AS INT)
I want to change all null values in [value] to 1 and then change all [value] to int so I can calculate this field.
You should have no issue converting a NULL value to an int, so I assume the issue is a string 'NULL'.
SQL Server offers TRY_CONVERT(). I recommend that you use that;
select try_convert(int, [value])
In other databases, you can use a regular expression to validate the data.
it will be is null that is not string
CAST( (CASE WHEN [value] is null THEN 1 ELSE [value] END) AS INT)
but its better to use try_convert what actually #Gordon recommend
Since you aren't actually looking for the NULL--which is the absence of data. You have bad data, i.e. the actual text 'NULL' in a column.
I would actually recommend you updating all the values to NULL so you can avoid doing try casting data to fix your problem. That would be something like:
UPDATE yourtable
SET [value] = NULL
WHERE [value] = 'NULL'
Then I would also change the column to a true INT type to avoid this in the future. But that's a bit outside the scope of your question.
Of course, you can't always change the data types. If you can, then this will be a more permanent solution.

MSSQL Server 2008 - Convert Nvarchar to numeric

im using mssql 2008 and Im permanently failing to convert an nvarchar to numeric values.
Can you please advise? I have different solutions I found over the www, but all of them are failing with the error message:
Msg 8114, Level 16, State 5, Line 15 Error converting data type
nvarchar to numeric.
I have built an reduced example for demonstration purpose:
IF OBJECT_ID('tempdb..#temptable', 'U') IS NOT NULL
DROP TABLE dbo.#temptable
create table #temptable(
col1 nvarchar(10),
col2 numeric(10,5)
)
insert into #temptable values ('0,5','0')
select *,convert(numeric(18,2),col1) from #temptable
UPDATE #temptable
SET col2 = CAST(col1 AS numeric(10,5))
WHERE ISNUMERIC(col1) = 1
SELECT col1
, CASE ISNUMERIC(col1)
WHEN 1 THEN CONVERT(numeric(18,2),col1)
ELSE 0.00
END
from #temptable
I alreay found an strong hint whats going wrong... the issue seems to be related to the , as seperator while the SQL server expects an .
if you change the following line to:
insert into #temptable values ('0.5','0')
its working
The problem is you are using ISNUMERIC(col1) = 1 which fails for a ton of cases like ISNUMERIC('1e4') or ISNUMERIC('$') or in your case, ISNUMERIC('1,000,000'). Don't use ISNUMERIC in this fashion.
Instead, try this...
UPDATE #temptable
SET col2 = CAST(col1 AS numeric(10,5))
WHERE col1 not like '%[^0-9.]%'
Use try_convert() in SQL Server 2012+:
UPDATE #temptable
SET col2 = TRY_CONVERT(numeric(10,5), col1)
WHERE ISNUMERIC(col1) = 1;
SQL Server re-arranges expression valuation in a query. So, the CAST() might be implemented before the WHERE -- resulting in the error. You can make a similar change to the SELECT version of your query.
In SQL Server 2008, you should be able to do effectively the same thing using CASE:
UPDATE #temptable
SET col2 = (CASE WHEN ISNUMERIC(col1) = 1 THEN CONVERT(numeric(10, 5), col1) END)
WHERE ISNUMERIC(col1) = 1;
Note: There may be cases where ISNUMERIC() returns "1", but the value cannot be converted (for instance, overflow). In that case, this version would still fail.

SQL Server : Nvarchar to Varchar

I have a table with two columns, one is of type Varchar and the other in NVarchar.
I want to update all the rows so VarcharField = NVarcharField.
It won't let me because some of the rows contain chars that are not allowed in varchar column with the current code page.
How can I find these rows?
Is it possible to remove any char that doesn't fit the specific code page I'm using?
SQL Server 2012.
You can find the rows by attempting to convert the nvarchar() col to varchar():
select nvarcharcol
from t
where try_convert(varchar(max), nvarcharcol) is null;
Try this..
to find the rows with values that are not supported by varchar
declare #strText nvarchar(max)
set #strText = 'Keep calm and say தமிழன்டா'
select cast(#strText as varchar(max)) col1 , N'Keep calm and say தமிழன்டா' col2
Here #strText has non-english chars, When you try to cast that into varchar the non-english chars turns into ????. So the col1 and col2 are not equal.
select nvar_col
from tabl_name
where nvar_col != cast(nvar_col as varchar(max))
Is it possible to remove any char that doesn't fit the specific code page I'm using?
update tabl_name
set nvar_col = replace(cast(nvar_col as varchar(max)),'?','')
where nvar_col != cast(nvar_col as varchar(max))
Replace ? with empty string and update them.
If Gordon's approach doesn't work because you get question marks from TRY_CONVERT instead of the expected NULL, try this approach:
SELECT IsConvertible = CASE WHEN NULLIF(REPLACE(TRY_CONVERT(varchar(max), N'人物'), '?',''), '') IS NULL
THEN 'No' ELSE 'Yes' END
If you need it as filter for the rows that can't be converted:
SELECT t.*
FROM dbo.TableName t
WHERE NULLIF(REPLACE(TRY_CONVERT(varchar(max), t.NVarcharField), '?',''), '') IS NULL

SQL Server, Select CASE with different casting

I want to do a select that do a cast only for a specific ID but it doesn't seems to work.
Example :
SELECT
CASE
WHEN(#ID <> 1) THEN Code
WHEN(#ID = 1) THEN Cast(Code AS int)
END Code FROM ....
Any Idea ?
Why do want to do this? A SQL Server expression has a single fixed type. In other words, a single expression can't be varchar(50) or int depending on how the expression is evaluated. You could cast each case to sql_variant, but that may or may not make sense based on what you're trying to do.
EDIT
If you are executing this query from a stored procedure, you could create an IF..ELSE block to execute a different version of the query based on the value of #ID. For example:
IF (#ID = 1) BEGIN
SELECT Cast(Code AS int) AS Code FROM ...
END
ELSE BEGIN
SELECT Code FROM ...
END
It works for me. Check if the #id is of type int and if all values of column Code can be casted to int.
UPDATE If you have a value that can't be casted to int, your query won't work.
So you can write 2 different queries.
Smth like
IF #id = 1 THEN
SELECT code ...
ELSE
SELECT Cast(Code AS int) as Code
You could have also written:
select case when #ID = 1 then CAST(Code as int) else Code end as Code
from...
By the way, any data containing alphabetic characters won't cast to int.
Perhaps could we better help you if you tell us what you want to achieve, with some sample data provided?

Like in CASE statement not evaluating as expected

Given this data:
CREATE TABLE tmpTable(
fldField varchar(10) null);
INSERT INTO tmpTable
SELECT 'XXX'
UNION ALL
SELECT 'XXX'
UNION ALL
SELECT 'ZZZ'
UNION ALL
SELECT 'ZZZ'
UNION ALL
SELECT 'YYY'
SELECT
CASE WHEN fldField like 'YYY' THEN 'OTH' ELSE 'XXX' END AS newField
FROM tmpTable
The expected resultset is:
XXX
XXX
XXX
XXX
OTH
What situation would casue SQL server 2000 to NOT find 'YYY'? And return the following as the resultset:
XXX
XXX
XXX
XXX
XXX
The problem is with the like 'YYY', I have found other ways to write this to get it to work, but I want to know why this exact method doesn't work. Another difficulty is that it works in most of my SQL Server 2000 environments. I need to find out what is different between them to cause this. Thanks for your help.
Check your service pack. After upgrading my SQL 2000 box to SP4 I now get the correct values for your situation.
I'm still getting the swapped data that I reported in my earlier post though :(
If you do SELECT ##version you should get 8.00.2039. Any version number less than that and you should install SP4.
I ran the code on a SQL 2000 box and got identical results. Not only that, but when I ran some additional code to test I got some VERY bizarre results:
CREATE TABLE dbo.TestLike ( my_field varchar(10) null);
GO
CREATE CLUSTERED INDEX IDX_TestLike ON dbo.TestLike (my_field)
GO
INSERT INTO dbo.TestLike (my_field) VALUES ('XXX')
INSERT INTO dbo.TestLike (my_field) VALUES ('XXX')
INSERT INTO dbo.TestLike (my_field) VALUES ('ZZZ')
INSERT INTO dbo.TestLike (my_field) VALUES ('ZZZ')
INSERT INTO dbo.TestLike (my_field) VALUES ('YYY')
GO
SELECT
my_field,
case my_field when 'YYY' THEN 'Y' ELSE 'N' END AS C2,
case when my_field like 'YYY' THEN 'Y' ELSE 'N' END AS C3,
my_field
FROM dbo.TestLike
GO
My results:
my_field C2 C3 my_field
---------- ---- ---- ----------
N XXX N XXX
N XXX N XXX
Y YYY N YYY
N ZZZ N ZZZ
N ZZZ N ZZZ
Notice how my_field has two different values in the same row? I've asked some others at the office here to give it a quick test. Looks like a bug to me.
It worked as expected on my SQL 2005 installation. If it works on other machines, it sounds like you've got an environment difference. Try comparing your connection properties in SQL Server Management Studio for a connection that works and one that doesn't to see if you can figure out what the differences are.
I am an Oracle person, not a SQL*Server person, but it seems to me you should be either:-
SELECT
CASE WHEN fldField like '%YYY%' THEN
'OTH'
ELSE 'XXX'
END AS newField
FROM
tmpTable
or ...
SELECT
CASE WHEN fldField = 'YYY' THEN
'OTH'
ELSE 'XXX'
END AS newField
FROM
tmpTable
The second is the direction I'd go in, as at least in Oracle equality resolves quicker than like.
When you use LIKE without specifying any search criteria, it behaves like an = comparison. In your example, I would expect it to work properly. In your real data, you probably have a hidden (non-printable) character in your data (think about Carriage Return, Line Feed, Tab, etc....).
Take a look at this example...
Declare #tmpTable TABLE(
fldField varchar(10) null);
INSERT INTO #tmpTable
SELECT 'XXX'
UNION ALL
SELECT 'XXX'
UNION ALL
SELECT 'ZZZ'
UNION ALL
SELECT 'ZZZ'
UNION ALL
SELECT 'YYY'
UNION ALL
SELECT 'YYY' + Char(10)
SELECT CASE WHEN fldField like 'YYY' THEN 'OTH' ELSE 'XXX' END AS YourOriginalTest,
CASE WHEN fldField like 'YYY%' THEN 'OTH' ELSE 'XXX' END AS newField
FROM #tmpTable
You'll notice that the last piece of data I added is YYY and a Line Feed. If you select this data, you won't notice the line feed in the data, but it's there, so your LIKE condition (which is acting like an equal condition) doesn't match.
The common 'hidden' characters are Tab, Carriage Return, and Line Feed. To determine if this is causing your problem...
Select *
From Table
Where Column Like '%[' + Char(10) + Char(9) + Char(13) + ']%'
What a cute bug. I think I know the cause. If I'm right, then you'll get the results you expect from:
SELECT
CASE
WHEN fldField like 'YYY ' -- 7 spaces
THEN 'OTH'
ELSE 'XXX'
END as newField
from tmpTable
The bug is that varchar(10) is behaving like char(10) is supposed to. As for why it doesn't, you'll need to understand the old trivia question of how two strings with no metacharacters can be = but not LIKE each other.
The issue is that a char(10) is internally supposed to be space padded. The like operator does not ignore those spaces. The = operator is supposed to in the case of chars. Memory tells me that Oracle ignores spaces for strings in general. Postgres does some tricks with casting. I have not used SQL*Server so I can't tell you how it does it.
How about fldField = '%YYY%'?
By adding (%) to the expression , it will work fine.
SELECT
CASE
WHEN fldField like '%YYY%' THEN 'OTH'
ELSE 'XXX' END AS newField
END
You aren't specifying what you are selecting and checking the CASE against...
SELECT CASE fldField WHEN 'YYY'
THEN 'OTH' ELSE 'XXX' END AS newField FROM tmpTable