Why this recursive concat produces: Data too long

时间秒杀一切 提交于 2019-12-24 20:16:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!