SQL isnull fails with try_cast - sql-server

I am trying to handle some data in the following way.
If the entry is numeric, cast it as an integer.
If the entry is not numeric, keep it as it is.
I am using 'try_cast' to cast my numeric entries to my integers. This gives NULL if the entry is not numeric.
declare #code varchar(3) = 'fff'
select try_cast(#code as int) as code
I then thought, well if I catch the null with an isnull I will be able to output the original value as I wanted.
declare #code varchar(3) = 'fff'
select isnull( try_cast(#code as int), #code) as code
However I get a conversion failed error.
I did not expect this behavior. Why is this happening and how can I acheive the desired behaviour?

TRY_CAST(... as int) return INT data type,
ISNULL(INT, VARCHAR(3)) leads both to INT
ISNULL: Returns the same type as check_expression.
declare #code varchar(3) = '123'
select ISNULL(CAST(try_cast(#code as int) as VARCHAR(3)),#code ) as code
may use
COALESCE: Returns the data type of expression with the highest data type
precedence
but INT upper VARCHAR in
Data type precedence

You are having a type-conversion error, because of the incompatibility. The column is either an integer or a string, but not both.
When you have two types in an expression, the numeric one dominates. In other words, SQL Server attempts to convert the string value to a number. Of course, this fails when done implicitly when try_convert() fails.
I would suggest two columns:
select try_cast(#code as int) as int_code, #code as orig_code

This is a block of code within a larger body of code, yes? As in, you're not trying to have a function dynamically return different data types based on the input?
If so, can you use sql_variant_property via an if-else block to direct flow of control? e.g.
declare #code varchar(3) = 'fff'
if SQL_VARIANT_PROPERTY(#code,'BaseType') = 'INT'
begin
print 'do numeric comparison'
end
else
begin
print 'do string comparison'
end

Related

Cast / convert a column but getting error

I have a column in database table defined as varchar(1000) null
In one of the situations, the data is entered as N/A - so I can force to ignore all values and use null.
But there are some values which I want to use.
If I use cast, convert, try_cast, tryconvert, to varchar all fails, but if I do it to int, it works, but the try cast, try convert works.
I am not sure why it is failing when I use try_cast and it says:
convert failed to convert N/A value to int.
Even I am not converting it to INT
Try the following:
DECLARE #test_val AS varchar(100) = 'N/A'
SELECT TRY_CAST(#test_val AS int)
This gives a result of NULL
DECLARE #test_val AS varchar(100) = '3'
SELECT TRY_CAST(#test_val AS int)
Gives a result of 3.
It may be that your SQL has a syntax error.

How to hold values in variable in sql server

I need to fetch max length of First_name and put it into #sq i am getting an error.
Declare #sq nvarchar(max)
Set #sq=''
SELECT MAX(LEN(FIRST_NAME)) FROM #table1
Drop table #t
SELECT CASE WHEN LEN(SEQ_NUM) = 0 THEN NULL ELSE SEQ_NUM END AS REC_NUM,
CASE WHEN LEN(FIRST_NAME) = 0 THEN NULL ELSE CONVERT(CHAR(Select #sq)),RTRIM(UPPER(FIRST_NAME))) END AS FIRST_NAME
into #t
from #tabel1
There's a few problem with this SQL. If we start with the first statement:
Set #sq=''SELECT MAX(LEN(FIRST_NAME)) FROM #table1
You have a couple of wayward single quotes here ('); not sure what they're doing. Secondly, if you're assigning a variables value from a dataset, the syntax is SELECT {Variable} = {expression} [,{Variable} = {expression} [,...]] FROM {etc} Thus you get:
SELECT #sq = MAX(LEN(FIRST_NAME))
FROM #table1;
The next statement, well, that's a mess. Firstly, there's also a wayward right parenthesis ()) here: RTRIM(UPPER(FIRST_NAME))) There should only be 2.
The expression CONVERT(CHAR(Select #sq)) is very wrong. CONVERT require 2 parameters, but only has one, and CHAR would return an character for the appropriate number provided. I.e. CHAR(65) returns A. I suspect you mean CONVERT(char,#sq) (you should really be declaring a length here!), however, #sq is already an nvarchar(max) (which is also pointless, as it's being assigned the value of an int). Thus I literally have no idea what you're trying to achieve here.
You need to assign the variable, like this:
Declare #sq int --LEN returns an int, not a varchar!
SELECT #sq = MAX(LEN(FIRST_NAME))
FROM #table1

CASE in sql server -implementation Clarification?

I have this simple table in sql server :
DECLARE #tbl table( a int , b NVARCHAR(100), isCalcByA bit)
INSERT INTO #tbl
SELECT 1,'c',1
UNION ALL
SELECT 2,'d',0
Ok.
If I run this :
SELECT CASE
WHEN isCalcByA = 1 THEN a
ELSE b
END FROM #tbl
It yields an error :
Msg 245, Level 16, State 1, Line 9
Conversion failed when converting the nvarchar value 'd' to data type int.
I can understand why it is happening :
Because the data which is being accumulated (to be displayed) can't attach both int and string at the same column .
Ok
But what about this :
SELECT 'dummy'
FROM #tbl
WHERE CASE
WHEN isCalcByA = 1 THEN a
ELSE b
END IS NOT NULL
Here -
I always display string
I don't accumulate different displaying results of different types.
I'm checking them against not null rather than a string or int value.
But still I get the same error .
What am I missing ?
NB
I know I can/should do this :
SELECT 'dummy'
FROM #tbl
WHERE
(isCalcByA = 1 AND a IS NOT NULL)
OR
(isCalcByA <> 1 AND b IS NOT NULL)
(which works fine)
But I'm asking why it is not working in the first CASE situation
CASE is an expression - it returns a value of a specific type. All possible values it might return must all be convertible to some common type. The system uses the type precedences rules to consider the types of all possible return values and decide what that common type is. int has higher precedence and wins.
CASE
WHEN isCalcByA = 1 THEN CONVERT(nvarchar(100),a)
ELSE b
END
would work because now the common type selected is unambiguously nvarchar(100).
No matter if you use CASE in the SELECT or the WHERE clause. CASE expressions should return the same datatype always. So, convert both columns to a datatype that can hold both:
CASE
WHEN isCalcByA = 1 THEN CAST(a AS NVARCHAR(100))
ELSE b
END
From the CASE expression documentation:
Returns the highest precedence type from the set of types in result_expressions and the optional else_result_expression.
When the various WHEN and the ELSE part have different datatypes as results, the highest precedence is chosen from this list: Data Type Precedence and all results are converted to that datatype.
Your queries fail because int has higher precedence than nvarchar.
DECLARE #tbl table( a int , b NVARCHAR(100), isCalcByA bit)
INSERT INTO #tbl
SELECT 1,'c',1
UNION ALL
SELECT 2,'d',0
UNION ALL
SELECT null,'d',1
SELECT CASE
WHEN isCalcByA = 1 THEN CAST(a AS VARCHAR(30))
ELSE b
END FROM #tbl
Above, you are selecting two different data types based on the select.
SELECT 'dummy'
FROM #tbl
WHERE CASE
WHEN isCalcByA = 1 THEN CAST(a AS VARCHAR(30))
ELSE b
END IS NOT NULL
Above, you are selecting 'dummy' every time, regardless of condition.
So, in the first statement, you are setting the return type based on the case and the case can return two different types. In the second query, the return type is always the same type.
Don't think about CASE like it is built-in IF from regular language. It's more like ... ? ... : ... operator with strong typing - it has to result in a specific singular type. If you want to mix columns you need to cast it to for example nvarchar.
You can also think about it like the result of SELECT should be possible to be defined by CREATE TABLE.

mssql convert varchar to float

I have a field value productlength of 0.123. This is from a view and has a data type of varchar.
I need to convert it to a float or numeric value so as o perform math comparisons.
convert(float,productlength)
and
cast(productlength as float) both do not work.
error varchar cant be converted to float or somethiing liek that.
From what I have read varchar can simply not be converted to a numeric string?
Any clever ways around this?
You can convert varchars to floats, and you can do it in the manner you have expressed. Your varchar must not be a numeric value. There must be something else in it. You can use IsNumeric to test it. See this:
declare #thing varchar(100)
select #thing = '122.332'
--This returns 1 since it is numeric.
select isnumeric(#thing)
--This converts just fine.
select convert(float,#thing)
select #thing = '122.332.'
--This returns 0 since it is not numeric.
select isnumeric(#thing)
--This convert throws.
select convert(float,#thing)
Use
Try_convert(float,[Value])
See
https://raresql.com/2013/04/26/sql-server-how-to-convert-varchar-to-float/
DECLARE #INPUT VARCHAR(5) = '0.12',#INPUT_1 VARCHAR(5)='0.12x';
select CONVERT(float, #INPUT) YOUR_QUERY ,
case when isnumeric(#INPUT_1)=1 THEN CONVERT(float, #INPUT_1) ELSE 0 END AS YOUR_QUERY_ANSWERED
above will return values
however below query wont work
DECLARE #INPUT VARCHAR(5) = '0.12',#INPUT_1 VARCHAR(5)='0.12x';
select CONVERT(float, #INPUT) YOUR_QUERY ,
case when isnumeric(#INPUT_1)=1 THEN CONVERT(float, #INPUT_1) ELSE **#INPUT_1** END AS YOUR_QUERY_ANSWERED
as #INPUT_1 actually has varchar in it.
So your output column must have a varchar in it.

Convert number stored as text data type to int

I have a database that is a result of an import. The database is a deliverable, I did not do the import myself, nor do I have access to the original data to do it myself. That being said, there is an integer value that was imported to a text datatype. All of the stored values are valid integers. I keep getting:
Explicit conversion from data type text to int is not allowed.
if I try to change the field data type in the table. I have also created a new INT field in the table and tried to update it based upon the value in the TEXT field, but I receive the same error. Lastly I tried to create a new table and tried to insert the old values but cannot convert or cast to the int successfully.
This seems to work: CONVERT(INT, CONVERT(VARCHAR(MAX),myText))
Edit:
I'm not totally sure of what's the best choice for the inner conversion... Choosing either VARCHAR(N) with N > 10 or VARCHAR(MAX) has the advantage of not preventing an overflow by truncating (assuming the overflow is the preferred behavior in that case).
Also, the conversion to INT seems to treat leading spaces as zero. So VARCHAR(MAX) reduces the chance of erroneously getting zero. E.g.:
CREATE TABLE #foo ( bar TEXT )
INSERT INTO #foo
VALUES (' 10')
SELECT CONVERT (INT, CONVERT(VARCHAR(MAX),bar)) FROM #foo -- 10
SELECT CONVERT (INT, CONVERT(VARCHAR(10),bar)) FROM #foo -- 0
Probably the best thing is to do some validation to make sure the input meets whatever your requirements are.
TextValue to Int direct Conversion is not possible, so
convert TextValue to varchar(max)
varchar(max) to int or bigint
Example :
convert(int, (convert( varchar(max),'TextValue'))) as ColumnName
You need to convert text type to varchar(x), after that you can cast or convert to int. To avoid double convert i prefer cast.
CAST(CONVERT(VARCHAR(50),CONFIG_VALUE) AS INT)
Full example:
DECLARE #age int;
SET #age = (SELECT CAST(CONVERT(varchar(50),#yourTextVarHere) AS INT))
SELECT #age

Resources