UNION causes "Conversion failed when converting the varchar value to int" - sql

I tried to search for previous articles related to this, but I can't find one specific to my situation. And because I'm brand new to StackOverflow, I can't post pictures so I'll try to describe it.
I have two datasets. One is 34 rows, 1 column of all NULLs. The other 13 rows, 1 column of varchars.
When I try to UNION ALL these two together, i get the following error:
Conversion failed when converting the varchar value to data type int.
I don't understand why I'm getting this error. I've UNIONed many NULL columns and varchar columns before, among many other types and I don't get this conversion error.
Can anyone offer suggestions why this error occurs?

The error occurs because you have corresponding columns in the two of the subqueries where the type of one is an integer and the type of the other is a character. Then, the character value has -- in at least one row -- a value that cannot be automatically converted to an integer.
This is easy to replicate:
select t.*
from (select 'A' as col union all
select 1
) t;
Here is the corresponding SQL Fiddle.
SQL Server uses pretty sophisticated type precedence rules for determining the destination type in a union. In practice, though, it is best to avoid using implicit type conversions. Instead, explicitly cast the columns to the type you intend.
EDIT:
The situation with NULL values is complicated. By itself, the NULL value has no type. So, the following works fine:
select NULL as col
union all
select 'A';
If you type the NULL, then the query will fail:
select cast(NULL as int) as col
union all
select 'A';
Also, if you put SQL Server in a position where it has to assign a type, then SQL Server will make the NULL an integer. Every column in a table or result set needs a type, so this will also fail:
select (select NULL) as col
union all
select 'A';
Perhaps your queries are doing something like this.

I have also encountered this error when I accidentally had the fields out of sequence in the 2 SELECT queries that I was unioning. Adjusting the fields' sequence fixed the problem.

Related

Unioned select statements cause an int overflow error

I am trying to run this unioned select statement and I'm getting an int overflow error.
The first select has an ID which is an integer so I've cast it as a varchar(25).
This levels the playing field, or so I thought, because the ID values in the subsequent two selects with a maximum size of varchar(25).
This is the error.
The conversion of the varchar value '24546133202216601' overflowed an int column
This might be a duplicate, but I couldn't find an identical question, so is there a way around this?
SELECT CAST(ID AS varchar(25)) AS thisID FROM tblA
UNION
SELECT ID AS thisID FROM tblB
UNION
SELECT ID AS thisID FROM tblC
From documentation
The data types must be compatible.
The definitions of the columns that are part of a UNION operation
don't have to be the same, but they must be compatible through
implicit conversion. When data types differ, the resulting data type
is determined based on the rules for data type precedence.

The data types in each column don't need to be compatible between the UNION queries

I read here that to be able to use SQL UNION queries,
data types in each column must be compatible between the individual queries.
So select a, b from table1 UNION select c, d from table2, for this query to work, we need a and c data types to be compatible.
However, when I try to test that, and make table users having two columns (id int, name varchar(15)), and table calc having two values (x int, y int), and after inserting elements
(1, 'saad') into table users, and values (3, 5) into table calc, and try query select * from users union select * from calc;, it shows the results as follows without any errors:
1 | saad
3 | 5
although name and y data types is not compatible, and was supposed to cause error
Conversion failed when converting the int value 5 to data type varchar
I thought it may be browser specific behavior, so I tried this also in google chrome, but it worked without any errors also!
Can someone explain to me why?
Thanks in advance.
Edit:
I'm using MySql 5.6
With MS SQL, there's a distinction between UNION and UNION ALL.
In the case of a UNION query, each value is compared to every other value for that column across all of select clauses. This might result in fewer records in final result than exist in the original select clause results. Even if you didn't intend for it, the optimizer will compare values from a and c along with b and d to find the uinion of those two sets. That also means that the datatype if they're different goes through an implicit data conversion to sql_variant to accomplish the goal of the union request.
Since UNION ALL is just stacking the sets one on top of each other, there's less of a need to compare the values.

UNION ALL Statement Failing

I am trying to UNION ALL around 20 or so tables to consolidate into a single view. I keep getting an error that states:
'The numeric value XXXXX is not recognized'.
This error is contained in 1 column in each of the tables, but the data type for that column is VARCHAR(256) in each of the tables. No matter what I cast the column to I still get the same error.
The UNION ALL works perfectly if I comment that column out.
I've tried casting all columns to the same datatype, no luck.
I've tried commenting out the column in question, which works, but I need that column.
I've tried only UNION-ing a few of the tables, which sometimes works and sometimes doesn't, depending on the document type.
SELECT
CAST(QUICKBOOKS_MEXICO.BILL_LINE.DESCRIPTION AS VARCHAR(256)) AS DESCRIPTION
FROM QUICKBOOKS_MEXICO.BILL_LINE
UNION ALL
SELECT
CAST(QUICKBOOKS_EUROPE_BV.PURCHASE_LINE.DESCRIPTION AS VARCHAR(256)) AS DESCRIPTION
FROM QUICKBOOKS_EUROPE_BV.PURCHASE_LINE
The columns should seamlessly UNION.
Here is the error message:
Numeric value 'Exchange Gain Or Loss' is not recognized
It's worth mentioning that if I remove all the other fields BESIDES the column that is throwing the error from the query, it performs just fine. Truly baffling!
It seems to me that the error message that you get is not related to this column, but with another column where you might be casting the data as NUMERIC, but instead getting this value 'Exchange Gain Or Loss'.
One way to ignore this conversion error, is to use TRY_CAST instead of CAST, so when a value can not be converted to the intended data type, it will simply return NULL

SQL secondary headers within data

I am having an issue that I haven't found an answer to. I wrote an SQL Query to generate a report that runs fine and outputs mostly numeric fields. The issue I'm running into is that we are putting it into a program that emails out files and it can only email out a .csv that does not include the header rows.
Is there a way to input the headers into the data? I've found a few solutions on here that didn't work for me. It seems like no matter what I do I get a data type error. This is all on an Oracle Database, the program we are using to send data out is called IQAlert, it's part of IQMS which is a manufacturing/erp system.
So far I've tried casting the headers as a number of numerical fields, a number of other solutions I found on here and other places on the internet such as changing to titles to varchar. The error I'm currently getting is
"ORA-01790: expression must have the same datatype as corresponding
expression"
Here is an extremely parsed down sample of the code. Adding the title "itemno' works fine because that field is text, when I try to add the header to onhand I get the data type error referenced above.
select 'itemno' as itemno, 'OnHand' as OnHand
from iqms.arinvt
union
select arinvt.itemno, arinvt.onhand
from iqms.arinvt
where itemno='10-00000000'
According to the documentation regarding The UNION [ALL], INTERSECT, MINUS Operators
You can combine multiple queries using the set operators UNION, UNION
ALL, INTERSECT, and MINUS. All set operators have equal precedence. If
a SQL statement contains multiple set operators, then Oracle Database
evaluates them from the left to right unless parentheses explicitly
specify another order.
The corresponding expressions in the select lists of the component
queries of a compound query must match in number and must be in the
same data type group (such as numeric or character).
If component queries select character data, then the data type of the
return values are determined as follows:
If both queries select values of data type CHAR of equal length, then
the returned values have data type CHAR of that length. If the queries
select values of CHAR with different lengths, then the returned value
is VARCHAR2 with the length of the larger CHAR value.
If either or both of the queries select values of data type VARCHAR2,
then the returned values have data type VARCHAR2.
If component queries select numeric data, then the data type of the
return values is determined by numeric precedence:
If any query selects values of type BINARY_DOUBLE, then the returned
values have data type BINARY_DOUBLE.
If no query selects values of type BINARY_DOUBLE but any query selects
values of type BINARY_FLOAT, then the returned values have data type
BINARY_FLOAT.
If all queries select values of type NUMBER, then the returned values
have data type NUMBER.
In queries using set operators, Oracle does not perform implicit
conversion across data type groups. Therefore, if the corresponding
expressions of component queries resolve to both character data and
numeric data, Oracle returns an error.
In short: in a query using one of the SET operators, for example like this:
SELECT x FROM table
UNION
SELECT y FROM table
where x is of numeric datatype, and yis of character datatype (or vice versa), then Oracle does not perform implicit conversion across data type groups and returns an error
Two simple examples:
SELECT 1 as X FROM dual
UNION
SELECT 'John' as Y FROM dual
ORA-01790: expression must have same datatype as corresponding expression
SELECT 'John' as X FROM dual
UNION ALL
SELECT 123 as Y FROM dual;
ORA-01790: expression must have same datatype as corresponding expression
Because Oracle does not perform implicit conversion, you must do an explicit conversion of one datatype to another datatype, the easiest one is to convert numbers to strings using TO_CHAR conversion function, like in this example:
SELECT 'John' as X FROM dual
UNION ALL
SELECT to_char(123) as Y FROM dual;
X
----
John
123
Maybe this will help. The first number is just sequence, the ROWNUM or ROW_NUMBER() can be used instead. The rest of numbers is simulated values:
SELECT itemno, onhand FROM
(
select 1 row_seq, NULL itemno, to_number(null) onhand from dual
union all
select 2, '5', 6 from dual
union all
select 3, '7', 8 from dual
)
WHERE row_seq > 1
/
Output:
ITEMNO ONHAND
5 6
7 8

ERROR: failed to find conversion function from unknown to text

There is an error on PostgreSQL that it gives on one of my select statements. I searched the web for an answer and came out empty handed. The answer given in another question did not suit my problem.
ERROR: failed to find conversion function from unknown to text
********** Error **********
ERROR: failed to find conversion function from unknown to text
SQL state: XX000
My query looks something like this:
Select *
from (select 'string' as Rowname, Data
From table)
Union all
(select 'string2' as Rowname, Data
From table)
The point of doing this is to specify what the row is at one point. The string being the name of the row. Here is my desired output:
Rowname Data
string 53
string2 87
Any possible way to fix this error?
Update: Type resolution in later versions of Postgres became smarter and this rule for UNION, CASE, and Related Constructs resolves it to text without explicit cast:
If all inputs are of type unknown, resolve as type text (the preferred type of the string category). [...]
SELECT 'string' AS rowname, data FROM tbl1
UNION ALL
SELECT 'string2', data FROM tbl2;
In older versions before Postgres 9.4 (?), or for non-default types you may still need to add an explicit cast like below.
Your statement has a couple of problems. But the error message implies that you need an explicit cast to declare the (yet unknown) data type of the string literal 'string':
SELECT text 'string' AS rowname, data FROM tbl1
UNION ALL
SELECT 'string2', data FROM tbl2;
It's enough to cast in one SELECT of a UNION query. Typically the first one, where column names are also decided. Subsequent SELECT lists with unknown types will fall in line.
In other contexts (like the VALUES clause attached to an INSERT) Postgres derives data types from target columns and tries to coerce to the right type automatically.
Select * from (select CAST('string' AS text) as Rowname, Data
From table) Union all
(select CAST('string2' AS text) as Rowname, Data
From table)
Reference