问题
I have this table on MySQL 8:
create table tbl(id varchar(2), val int);
insert into tbl values ('A', 1), ('B', 2), ('C', 3), ('D', 4), ('E', 5);
The following query should find out which record sets have values that add up to a value not greater than 6 (without importance of order):
with recursive cte(greatest_id, ids, total) as (
select id,
concat(id, ''),
val
from tbl
union all
select tbl.id,
concat(cte.ids, tbl.id),
cte.total + tbl.val
from cte
inner join tbl
on tbl.id > cte.greatest_id
and cte.total + tbl.val <= 6
)
select ids, total from cte
Running it results in the following error:
Error: ER_DATA_TOO_LONG: Data too long for column
concat(id, '')
at row 7
Why does MySQL produce this error?
For info, the desired output is below:
IDS | TOTAL
----+------
A | 1
B | 2
C | 3
D | 4
E | 5
AB | 3
AC | 4
AD | 5
AE | 6
BC | 5
BD | 6
ABC | 6
I want to know by which (documented?) rule MySQL produces this error here.
By comparison, the query works fine on PostgreSQL and Oracle (using their syntax variation), so I don't really understand why MySQL is having a problem with it.
回答1:
A long way down the MySQL 8 CTE manual page is an example that shows the problem you are having. Basically the problem is that your ids
column is too narrow for the ABC
value being assigned to it as it gets its width from the non-recursive part of the CTE (which is effectively the length of id
i.e. 2 characters). You can solve that problem with a CAST
to a big enough width to fit all the results e.g.:
with recursive cte(greatest_id, ids, total) as (
select id,
CAST(id AS CHAR(5)) AS ids,
val
from tbl
union all
select tbl.id,
concat(cte.ids, tbl.id),
cte.total + tbl.val
from cte
inner join tbl
on tbl.id > cte.greatest_id
and cte.total + tbl.val <= 6
)
select ids, total from cte
Update of your demo
来源:https://stackoverflow.com/questions/54732559/why-this-recursive-concat-produces-data-too-long