Matching two values of different types in two SQL databases - sql

I am trying to compare records between two different SQL tables/databases in my Node project and have to do some transformation in order to compare the values.
In one database (MariaDB) the value is of type INT, and looks like this: 516542
In the other (SQL Server) database the value I need to match to is of type char(21), and looks like this: 00000516542-000
What I tried doing was this:
WHERE (REPLACE(LEFT( LM301.DOCNUMBR, CHARINDEX('-', LM301.DOCNUMBR)), '-', '')) = 516542
This works for some records, but for others I get this error:
"The conversion of the varchar value '0004000009123' overflowed an int
column."
If I pass the first value in as a string ('516542') it doesn't match at all.
How can I handle this scenario?

The error you're getting is at least correct. But from your example i can't determine whether the conversion is right or not.
Basically, somewhere in your CHAR(21). There a value which is greater than int32, or SQL Server int type, in value. This value is: 2,147,483,648. 4,000,009,123 is greater than this max value as specified by the error message.
The DBMS, with this where statement, will try to do the operation and compare to all records, and it runs into an overflow. You could do a string compare instead. Or try an explicit conversion and convert it to bigint.
WHERE CONVERT(BIGINT, (REPLACE(LEFT( LM301.DOCNUMBR, CHARINDEX('-', LM301.DOCNUMBR)), '-', ''))) = 516542
It's doing an implicit cast to INT because that's your compare type, then overflows. Making the conversion explicit allows you to determine the datatype instead.
Basically what's happening:
IF ('21474836480' >= 100) --Implicit conversion: Error and prints false
PRINT 'True'
ELSE
PRINT 'False'
IF ('214748364' >= 100) --Implicit Conversion: True
PRINT 'True'
ELSE
PRINT 'False'
IF (CONVERT(BIGINT, '21474836480') >= 100) --Explicit Conversion: Prints True
PRINT 'True'
ELSE
PRINT 'False'
So wrapping your value in an explicit conversion should resolve your error.

You need to do explicit type conversation with TRY_CONVERT():
TRY_CONVERT(BIGINT, LEFT(LM301.DOCNUMBR, CHARINDEX('-', LM301.DOCNUMBR + '-') - 1)) = 516542
TRY_CONVERT() will return NULL if conversation fail.
You don't need to use replace(), you can subtract the position.
EDIT : Try_CONVERT() is available from 2012 +. For older version you can do :
(CONVERT(BIGINT, LEFT(LM301.DOCNUMBR, CHARINDEX('-', LM301.DOCNUMBR) - 1)) = 516542 AND
CHARINDEX('-', LM301.DOCNUMBR) > 0)
)
Note : This might fail if DOCNUMBR doesn't have numeric value prior to -.

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

Why is SQL Server trying to convert my nvarchar(20) datatype to an int?

I'm getting the "conversion" error in a SQL Select query.
The error is:
Msg 248, Level 16, State 1, Line 6
The conversion of the nvarchar value '7000952682' overflowed an int column.
Problem is, there are no int columns in my table!
Here is the table structure:
Here is the query:
If I set the value of #SU to NULL, then it does return all rows as expected. When the value is set to the string value of '7000952682' I get the error.
Why is SQL Server trying to convert the nvarchar value to an int?
All branches of a CASE expression have to have the same type. In this case (no pun intended), it looks like SQL Server is using an integer type and doing an implicit cast of SU to integer. The problem is that the max value for an integer in SQL Server is roughly 2.1 billion, and the example you gave is using the value 7000952682, hence the overflow.
You have two options here. You could make everything varchar:
CASE WHEN #SU IS NULL OR #SU = '' THEN '1' ELSE [SU] END
Or, you could make everything numeric, using a type that won't overflow, e.g.
CASE WHEN #SU IS NULL OR #SU = ''
THEN CAST(1 AS numeric(20, 6))
ELSE CAST([SU] AS numeric(20, 6)) END
As a side note, you could write the first part of your CASE expression more succinctly using COALESCE:
CASE WHEN COALESCE(#SU, '') = '' THEN '1' ELSE [SU] END
Don't use case in the where clause. The logic is more simply and accurately expressed as:
where (#su is null or #su = '' or #su = su)

REPLACE to just have a number causing conversion failure

I'm trying to do a count to see how many fields in column value are > 10:
SELECT
COUNT(CASE WHEN t.value > 10)
THEN 1
ELSE NULL
END
FROM table t
WHERE t.DATE = '2017-01-01'
However, the column has a few custom entries like +15 or >14.0, so I added the following:
SELECT
COUNT(CASE WHEN value LIKE '>%'
and Replace(value, '>', '') > 10)
FROM table t
WHERE t.DATE = '2017-01-01'
However, after doing that, I get the following error:
Conversion failed when converting the varchar value '>14.0' to data
type int. Warning: Null value is eliminated by an aggregate or other
SET operation.
Seeing I have no access to rewrite the database with an UPDATE, does anyone have a workaround solution?
You could fix this, either by simply changing 10 to 10.0:
SELECT CASE WHEN '14.0' > 10.0 THEN 1 ELSE 0 END
This will cause the implicit conversion of '14.0' to decimal rather than int, which works, or you explicitly convert it:
SELECT CASE WHEN CONVERT(DECIMAL(14, 2), '14.0') > 10 THEN 1 ELSE 0 END
If it were me however, and I was not in a position to update the data, and do something a bit left field, like use a numeric data type to store numbers, I would ignore these values completely, and simply use TRY_CONVERT to avoid the conversion errors:
SELECT
COUNT(CASE WHEN TRY_CONVERT(DECIMAL(14, 2), value) > 10 THEN 1 END)
It is a varchar column, so the possibilities of what nonsense could be in there are endless, you might get a query that works now by replacing > and +, but then what about when someone puts in <, or ends up with a space in between like + 14, or something completely random like 'aaaa', where does it end?
It would be helpful to see the table and sample data, but it sounds like you have strings that are numbers and a sign.
You can cast it to convert the data since you are mixing and matching data types.
SELECT
COUNT(CASE WHEN CAST(value AS VARCHAR(10)) LIKE '>%'
and CAST(Replace(value, '>', '') AS your_num_datatype_here) > 10)

T-SQL NULLIF returns NULL for zero

Why the script below returns NULL instead of 0?
DECLARE #number BIGINT = 0;
SELECT NULLIF(#number, '');
According to the MSDN, it should return 0:
NULLIF
Returns a null value if the two specified expressions are equal.
For SQL server, 0 and '' is considered the same (=equal)? What is the logic behind?
When an operator combines two expressions of different data types, the rules for data type precedence specify that the data type with the lower precedence is converted to the data type with the higher precedence.
SELECT CONVERT(bigint, '')
SELECT CONVERT(float, '')
SELECT CONVERT(date, '')
0
0
1900-01-01
https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-precedence-transact-sql
As BOL states: "the rules for data type precedence specify that the data type with the lower precedence is converted to the data type with the higher precedence."
You've got two different datatypes, bigint and nvarchar. In order to compare the two, they have to be the same datatype. Following the rule described, the nvarchar is implicitly converted to bigint. Try select convert(bigint, ''), you'll find it results in 0. So they are the same.
This script should return null and it is true!
The reason behind it is '' is a string, so it will get implicitly casted to an integer value when comparing it with an integer as you are doing now!
In general, you're asking for trouble when you're comparing values of different data types, since implicit conversions happen behind the scene.
This is the result of implicit conversion. In some cases a string value can be converted to an integer (such as empty string is converted to 0).
Essentially SQL Server tries to match the data type of the two expressions first, then it checks the values.
DECLARE #number BIGINT = 0;
SELECT
CONVERT(BIGINT, '')
, NULLIF(#number, '')
, NULLIF(#number, CONVERT(BIGINT, ''))
It has converted '' to the integer which is 0, as integer has higher precedence in data type. Check the example below how '' become 0
SELECT CONVERT(INT, '') -- 0
SELECT CAST('' AS INT) -- 0

"Error converting data type nvarchar to float" with CASE WHEN Statement

I'm trying to run a query with the following as one of the select statements, and I keep getting the error "Error converting data type nvarchar to float." I've been converting VBA IIf statements to CASES and I can't seem to get the conversions right. fld2 is nvarchar(15) and fld1 is a float data type. I need help pinpointing why this error is being thrown.
CASE WHEN (IsNumeric([fld2]) = 1) THEN Round(Convert(nvarchar,[fld2]) +
' / ' + Convert(nvarchar,[fld1]),(Len(Convert(nvarchar,[theData])) -
Charindex(Convert(nvarchar, [fld2]),'.'))) ELSE [fld2] END,
As is, your example would produce quite a funny expression for SQL server to evaluate. Let's substitute values for fld1, fld2, and theData as an example to see what you're trying to do:
[fld1] = 42.0
[fld2] = N'69.56'
[theData] = N'something'
(an N before a string makes it an nvarchar instead of varchar)
With substitutions, the resulting query would look like this:
CASE WHEN (IsNumeric(N'69.56') = 1) THEN
Round(Convert(nvarchar,'69.56') + ' / ' + Convert(nvarchar, 42.0),
(Len(Convert(nvarchar,'something')) - Charindex(Convert(nvarchar, N'69.56'),'.')))
ELSE
N'69.56'
END
Since you don't need to convert an nvarchar to nvarchar explicitly, your query actually looks more like:
CASE WHEN (IsNumeric(N'69.56') = 1) THEN
Round(N'69.56 / ' + Convert(nvarchar, 42.0),
(Len(N'something') - Charindex(N'69.56','.')))
ELSE
N'69.56'
END
So there are a couple of problems:
You're passing a varchar value into the ROUND() function, which expects a numeric value, not an expression
The two paths of the CASE statement are returning different types
What I think your query should look like is:
CASE WHEN IsNumeric([fld2]) = 1 THEN
CONVERT(nvarchar, ROUND(CONVERT(float, [fld2]) / [fld1],
(LEN([theData]) - CHARINDEX([fld2], '.'))))
ELSE
[fld2]
END
The above does the math and rounding on numeric results instead of strings, doesn't do any unnecessary conversions, and also returns the same type in both cases.