Is it possible to convert nvarchar to int? - sql-server

I have tried something like this:
select PREPRO = case when (isnumeric(PREPRO) = 1 and
PREPRO in ('0','1','-1')) or
convert(varchar, PREPRO) in ('True','False')
then convert(bit, convert(integer, PREPRO)) else 'No' end
from dbo.TI10SE
The PREPRO contains all "False".
I get this error:
Conversion failed when converting the nvarchar value 'False' to data type int.
Does it mean that an nvarchar can not be converted to an integer ever? I guess its because some data may be lost.

You are trying to convert your PREPRO to an integer, even if the value it holds is True or False:
convert(integer, PREPRO)
You cannot convert the value False to an integer.
The conditional in your when clause evaluates to true when PREPRO is a number within 0, 1, -1 OR when it evaluates to either True or False. In any of these cases, you attempt to convert this value to an integer and then to a bit.

Use CASE to accomplish this:
DECLARE #PREPRO VARCHAR(5)
SET #PREPRO = 'False'
SELECT CASE WHEN #PREPRO = 'False' THEN 0 ELSE 1 END

nvarchar can be converted to an integer if it contains an integer
DECLARE #PREPRO VARCHAR(5)
SET #PREPRO = '10'
SELECT CONVERT(integer, #PREPRO)
T-SQL doesn't know what to associate with 'False' or 'True', so you will have to use a CASE statement like rdkleine said.
Also in this statement:
convert(bit, convert(integer, PREPRO)) else 'No' end
You're going to receive an error, because 'No' is not of type bit, what are you trying to return?

Related

SQL isnull fails with try_cast

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

How to convert NVARCHAR to BIT in mssql

I am new to mssql , Here I receive a parameter as "NVARCHAR" but the column datatype is BIT so I need to convert the Nvarchar data as Bit data.
Here the Nvarchar data is always either "True" or "False".
INSERT INTO EC_CUSTOMER_PROFILE(
CP_SEND_NEWS_LETTER,
CP_SEND_PARTNER_SPECIAL_OFFER,
CP_CREATION_DATE,
CP_CREATED_BY)
VALUES(
#mNewsLetter, //Nvarchar(50)
#mSpecialOffer, //Nvarchar(50)
GETDATE(),
#mUserId)
Can anyone help me to fix it .
Just use a CASE expression, e.g.
CASE #mSpecialOffer WHEN 'TRUE' THEN 1 ELSE 0 END
so...
INSERT INTO EC_CUSTOMER_PROFILE(
CP_SEND_NEWS_LETTER,
CP_SEND_PARTNER_SPECIAL_OFFER,
CP_CREATION_DATE,
CP_CREATED_BY)
VALUES(
CASE #mNewsLetter WHEN 'TRUE' THEN 1 ELSE 0 END,
CASE #mSpecialOffer WHEN 'TRUE' THEN 1 ELSE 0 END,
GETDATE(),
#mUserId)
Just cast it as bit.
The strings True and False are interpreted as you would expect.
INSERT INTO EC_CUSTOMER_PROFILE
(CP_SEND_NEWS_LETTER,
CP_SEND_PARTNER_SPECIAL_OFFER,
CP_CREATION_DATE,
CP_CREATED_BY)
VALUES ( CAST(#mNewsLetter AS BIT),CAST(#mSpecialOffer AS BIT),GETDATE(),#mUserId)
INSERT INTO EC_CUSTOMER_PROFILE(
CP_SEND_NEWS_LETTER,
CP_SEND_PARTNER_SPECIAL_OFFER,
CP_CREATION_DATE,
CP_CREATED_BY)
VALUES(
CASE WHEN #mNewsLetter = 'True' THEN 1
WHEN #mNewsLetter = 'False' THEN 0
END,
CASE WHEN #mSpecialOffer = 'True' THEN 1
WHEN #mSpecialOffer = 'False' THEN 0
END,
GETDATE(),
#mUserId)

T-SQL unexpected behavior in isnull function

When i run this query i expect the result will be 'false'
IF isnull(0,'') = ''
select 'true'
else
select 'false'
But sql Server tells me 'true', why?
In this case ISNULL(0,'') returns an integer. SQL Server will cast the second argument to an integer too, ie 0. So 0=0, hence the result is TRUE. Comparing directly to 0 would also return true:
IF 0 = ''
select 'true'
else
select 'false'
Using ISNULL and NULL like this is unusual. An ISNULL(someColumn='') function in a WHERE clause would prevent the optimizer from using any indexes that covered someColumn thus forcing a scan instead of an index seek.
Using IF statements in SELECT is impossible. Even in CASE statements, it's better to explicitly check for NULL than apply such transformations.
For your case, when compare two values, the '' will be converted to int first. The following:
SELECT CONVERT(INT, '')
returns 0, so 0=0 is true
If you want treat 0 as NULL, you can use NULLIF:
DECLARE #i INT = 0
IF NULLIF(ISNULL(#i, ''), 0) = ''
SELECT 'true'
ELSE
SELECT 'false'
This would return 'false'
ISNULL are identical when there are just two values (i.e. NULL and 0) so, it will be true in IF condition and select 'true' will be printed.

Conversion failed when converting the varchar value 'No' to data type tinyint

I have one SQL server table which has one tinyint column. The value of the column will be 0 or 1 or 2.
If it is "0", I have to show "No".
If it is "1", I have to show "Yes".
If it is 2, it needs to show just 2.
Below is my Query,
select
case when flag=1 then 'Yes'
when flag=0 then 'No'
else flag
end flag
from Employee
When I execute this query I'm getting below exception,
Conversion failed when converting the varchar value 'Yes' to data type tinyint.
You can't mix the data types in a case. Cast the number output to a string
select case when flag=1 then 'Yes'
when flag=0 then 'No'
else CAST(flag AS CHAR(1))
end flag
from Employee
Your Else part is of type TinyInt other case statements return Varchar. This causes the issue. You can get rid of the issue by using the below.
(The SQL is similar to Juergen post but with minor change)
select case when flag=1 then 'Yes'
when flag=0 then 'No'
else CAST(flag AS Varchar(3))
end flag
from Employee
The size of Tiny Int is 0-255 so we can convert to Varchar(3)

SQL Server: Case statement is displaying Msg 8115, Arithmetic overflow error converting varchar to data type numeric

I have the following query which is throwing:
Arithmetic overflow error converting varchar to data type numeric.
Query:
Select
#Fee = Case
When IsNull(Fee, '') = '' Then 0.00
Else Fee
End
#Fee is of type Money, and Fee is Varchar type.
I have also observer that for following types of data in Then clause no error is being displayed.
Select #Fee = Case When IsNull(Fee, '') = '' Then 1 Else Fee End
Select #Fee = Case When IsNull(Fee, '') = '' Then 1.0 Else Fee End
So only for values 0.00 or 0.0 in Then clause I am getting error.
I have also tested with below query and worked fine:
Select #Fee = Case When IsNull(Fee, '') = '' Then Cast(0.00 as money) Else Fee End
And more interesting thing is that, as per data we have in table, Then part of the Case statement will never be executed. Please help me understanding this behavior of Case statement.
I have played around this and this is what happens:
DECLARE #v VARCHAR(20) = '1'
SELECT CASE WHEN '' <> '' THEN 0.00 ELSE #v END col1 INTO tempTable
When you will execute the above query you will see error but the table will be created and the type of the column created col1 is numeric(2,2). If you change to 0.0000 the type will be numeric(4,4). This means that actually the type of an expression depends on that value. Also (2,2) means that you can store only values with length 2 and everything goes after dot(.12, .25 etc). So it can not cast 1.00 to numeric(2,2) because the type doesn't allow to have digits before dot.
The best rule here is to always return the same types from different paths of case expression.
This is from Microsoft about return type of case expression (https://msdn.microsoft.com/en-us/library/ms181765.aspx):
Returns the highest precedence type from the set of types in
result_expressions and the optional else_result_expression. For more
information, see Data Type Precedence (Transact-SQL).
This is about type precedence where you can see that numeric precedes varchar(https://msdn.microsoft.com/en-us/library/ms190309.aspx). So the return type of your case expression becomes numeric(2,2) and this is the answer to your question.
I will also give you an advise: never store money values in varchar columns. Always store values in appropriate type(there are so many types available that all your needs will be satisfied).
You have a CASE expression that returns two different datatypes - that's always a really bad idea....
Select
#Fee = Case
When IsNull(Fee, '') = '' Then 0.00
Else Fee
End
When Fee is in fact NULL, you return 0.00 - a numerical value
When Fee (varchar) is NOT NULL, then you return that value - a string
Since both cases are assigned to one and the same #Fee variable - SQL Server must coerce these into the same datatype - whatever #Fee dictates (money in your case).
And for some reason, in the case of Fee being NOT NULL, that seems to fail at times.
So the point is: whenever possible, return the same datatype from all your possible values in a CASE statement - and do so explicitly (using a CAST or CONVERT) - don't force SQL Server to handle this for you
the code will reproduce your issue
DECLARE #Fee MONEY
DECLARE #test VARCHAR
SELECT #Fee = ISNULL(#test, 0.00)
Select #fee
but this one is the fix
DECLARE #Fee MONEY
DECLARE #test VARCHAR
SELECT #Fee = ISNULL(#test, '0.00')
Select #fee

Resources