Cast giving an error - sql-server

Why is this simple code giving me an error:
Conversion failed when converting the varchar value '3.0' to data type
int.
select cast(value as INT)
from CV3BasicObservation (nolock)
where value >= 110

SQL Server doesn't want to convert a number string that looks like a decimal to integer because you could lose precision. You could trick it with the round function:
select cast(round(value,0) as INT)
from CV3BasicObservation (nolock)
where cast(round(value,0) as INT) >= 110
NOTE: You have to do it to all instances of the field value where you are explicitly converting it to int or where it is implicitly converting it for comparison an int type value.

Related

T-SQL Scientific notation field conversion

I load excel file into sql as varchar(max) and got that Scientific e value which now I try to convert into numeric as I need to do compare that value, and here I'm running into problem.
This is main question: How and to what type I can convert this to compare with whole integer value ?
On the pic You can see how this seen in Excel, even formatted to text it somehow still loaded into varchar(max) not like char string. This can be seen from my test code.
DECLARE #C VARCHAR(MAX) = '1.1001562717e+011', #Nc VARCHAR(MAX) = '110015627174';
SELECT #c, LEN(#c) LenC ,
ISNUMERIC(#c) NumYN
---, CAST(#c AS DECIMAL(38,2)) cDec ---CAST(#c AS NUMERIC) cNum --, CAST(#c AS BIGINT) cInt
WHERE #c LIKE '%[^0-9]%'
AND ISNUMERIC(#c) = 1
To start, ISNUMERIC is a terrible function, it does not give good results; it is often wrong. If you try ISNUMERIC('1.1001562717e+011') you'll notice that you get the value 1, however, CONVERT(numeric(13,1),'1.1001562717e+011') will produce an error. A far better function is TRY_CONVERT (or TRY_CAST), which returns NULL if the conversion fails for the specific data type: TRY_CONVERT(numeric(13,1),'1.1001562717e+011').
Being specific on the data type is actually important here, as ISNUMERIC could be (incorrectly) suggesting that the value could be converted to at least 1 of the numeric data types; but that doesn't mean all of them. For scientific data types the only data type you can convert to is a float/real:
SELECT TRY_CONVERT(numeric(13,1),'1.1001562717e+011') AS Numeric,
TRY_CONVERT(bigint,'1.1001562717e+011') AS int,
TRY_CONVERT(float,'1.1001562717e+011') AS float,
TRY_CONVERT(money,'1.1001562717e+011') AS money;
Notice that only float has a value here. As you want a numeric as the final value, then you'll need to CONVERT the value twice:
CONVERT(numeric(13,1),TRY_CONVERT(float,'1.1001562717e+011'))

How can I convert a float into int using the 'round' method in SQL Server?

I tried with
select ROUND(1235.53)
--(It can contain "n" digit of scale)
But I got this error:
The round function requires 2 to 3 arguments.
I am not sure what is the use of other parameters.
Set decimals to zero
select cast(ROUND(1235.53,0) as int) Returns 1236
select cast(1235.53 as int) Returns 1235
Better to use CAST INT/CEILING/FLOOR:
SELECT CEILING(1235.53)
SELECT FLOOR(1235.53)
SELECT CAST(1235.53 AS INT)
CEILING: Gives you the upper bound integer value
FLOOR: Gives you the lower bound integer value
Here is another approach that just formats the result into the desired format:
SELECT FORMAT(ROUND(1235.53,0), 'N0')
'N' stands for numerical format and the digit behind it controls the number of decimal points.

How does T-SQL implicit conversion / overload resolution work?

I've been toying around with T-SQL in an attempt to understand the implicit conversion and overload resolution rules, but somehow it seems to work a bit strange...
Context:
Data type conversion: https://msdn.microsoft.com/en-us/library/ms191530.aspx
Data type precedence: https://msdn.microsoft.com/en-us/library/ms190309.aspx
Abs: https://msdn.microsoft.com/en-us/library/ms189800.aspx
Basically the latter tells you that abs will work on int, float, decimal, etc. So let's see how that works:
declare #foo2 sql_variant;
set #foo2 = abs(4);
select sql_variant_property(#foo2, 'BaseType')
-- result: int. OK, apparently we have an int overload. As expected.
declare #foo2 sql_variant;
set #foo2 = abs(cast(4.0 as float));
select sql_variant_property(#foo2, 'BaseType')
-- result: float. OK, apparently we have a float overload. As expected.
Now, according to the implicit type conversion table, we are allowed to implicitly convert stuff. We're going to check this by converting a varbinary to int, which should happen according to the type precedence rules:
declare #foo varbinary(4);
set #foo = cast(4 as varbinary(4));
select #foo + 2;
-- result: int. OK, as expected.
From this result I would expect the following to work as well:
declare #foo varbinary(4);
set #foo = cast(4 as varbinary(4));
select abs(#foo);
-- result: error: Operand type clash: varbinary is incompatible with float
Stuff I don't understand here (the question):
Why does the implicit conversion pick the 'float' overload of the 'abs'? Is this just a random overload? Or perhaps the overload that's highest in the precedence list (which happens to be 'float')?
Why isn't implicit conversion applied from varbinary -> int? After all, it's a perfectly valid conversion.
From MSDN for Abs:
Arguments
numeric_expression
Is an expression of the exact numeric or approximate numeric data type category.
I guess that calling Abs( varbinary ) would try to convert the varbinary to an exact numeric or approximate numeric data type.
Float is at the top of Data Type Precedence for these types so there is the problem I guess.
UPDATE with my logic
declare #foo varbinary(4);
Declare a varbinary variable.
set #foo = cast( 4 as varbinary(4));
Set to this variable a value by performing an explicit cast from int to varbinary which is perfectly doable.
select sql_variant_property(#foo, 'BaseType')
This shows that the variable is of type varbinary.
select abs(#foo);
Try to run abs on varbinary.
The error message is clear:
Operand type clash: varbinary is incompatible with float
So my guess is that abs is trying to implicit convert varbinary to the first of the Data Type Precedence for exact numeric or approximate numeric data types which is float.
This conversion fails according to CAST and CONVERT chart.
I hope I've got this right! Comments appreciated.
You've found the conversion and precedence MSDN pages so let's take your example apart.
declare #foo varbinary(4);
set #foo = cast(4 as varbinary(4));
Now, what type is foo?
SELECT SQL_VARIANT_PROPERTY(#foo,'BaseType')
--------
varbinary
Good so far so good. But what's 'in' #foo ?
SELECT #foo
----------
0x00000004
Now, ABS() accepts a numeric - a floating point number:
What does 4.00 look like compared to 4? Let's try:
SELECT CONVERT(VARBINARY(MAX), 4.00) ,CONVERT(VARBINARY(MAX), 4);
------------------ -----------------------
0x0302000190010000 0x00000004
See the internal representation of 4.00 is different to 4? It's storing precision, scale and the value whereas your 'int in a varbinary' isn't.
And that's why the conversion fails. ABS() accepts a numeric, your 'wrong format' varbinary cannot be coerced to a numeric as it's not one, it's some other representation - we know it represents an int but SQL Server doesn't.
If you want to add a floating point number to an int that's 'inside' a varbinary, you have to do something like
select CONVERT(INT, #foo) + 2.0
Back to your example:
declare #foo varbinary(max);
set #foo = cast(4.00 as varbinary(max));
SELECT ABS(#foo+2.0)
----------
6.0
4.00 is converted into a varbinary in the correct internal format, and happily coerced into a numeric by the ABS() call. Happy days.

How do I do decimal arithmetic on two varchars and return result to an aliased column?

I have two fields of type varchar that contain numeric values or blank strings, the latter of which I have filtered out to avoid Divide by Zero errors.
I am attempting to determine the percentage value that num2 represents in relation to num1, i.e. (Num_2 * 1 / Num_1). Relatively simple math.
The problem I am having is that I cannot seem to do the math and then cast it to a decimal value. I keep receiving Arithmetic overflow error converting int to data type numeric errors.
Can someone help me out with the casting issue?
You didn't interpret the error correctly.
It is not about casting the result of your math to float, it is about implicit type casting before the equation is evaluated.
You have in your table some values that cannot be converted to numeric, because they are not valid numbers or numbers out of range. It is enough that one row contains invalid data to make fail the whole query.
perhaps you're looking for something similar to this?
declare #table table (
[numerator] [sysname]
, [denominator] [sysname]);
insert into #table
([numerator],[denominator])
values (N'1',N'2'),
(N'9999999999',N'88888888888');
select case
when isnumeric([numerator]) = 1
and isnumeric ([denominator]) = 1
then
cast([numerator] as [float]) / [denominator]
else
null
end
from #table;
Is this what you're looking for?
select cast('25.5' as decimal(15, 8)) / cast('100.0' as decimal(15, 8))
The example above will return this:
0.25500000000000000000000
In this case, I'm converting the operand types before they get used in the division.
Remember to replace the literals in my query by your field names.
you said that can be number or blank string.
son try something like this:
SELECT
(CASE WHEN NUM_2 = '' THEN 0 ELSE CAST(NUM_2 AS NUMERIC(15,4)) END)
/
(CASE WHEN NUM_1 = '' THEN 1 ELSE CAST(NUM_1 AS NUMERIC(15,4)) END)
you test if string is blank. if it is, you use 0 (or 1, to avoid division by zero)

SQL Server CAST from varchar to numeric fails with error

I have a column of data that contains 9 digits of numeric values, but the column is defined as a varchar. I need to CAST the field to a numeric value so I can divide the sum of the column by 100. e.g.
select CAST(field1 as numeric(9,2)) / 100 from table;
I get the following error when running the query: Arithmetic overflow error converting varchar to data type numeric.
If I perform a double CAST from varchar -> int -> numeric, the CAST works. e.g.
select CAST(CAST(field1 as int) as numeric(9,2)) / 100 from table;
Is there a reason why the single CAST from varchar -> numeric results in a SQL error, but the double CAST works?
If your field contains 9 digits, it could be a max of 999,999,999. My original thought was that your cast should be CAST (NUMERIC 11, 2)
edit
To be on the safe side, with 9 character length, you could have numbers ranging from 999,999,999 to 0.1234567. This means you need 9 digits before the decimal point and 7 after (total 16). Therefore your cast should be CAST (NUMERIC (16,7)
select CAST(field1 as numeric(16,7) from table;
The cause of the error was one row that had '-' as the value for the field. CASTing directly to NUMERIC doesn't work, but CASTing to INT first forced the '-' fields to return 0.

Resources