我在MySQL 8上有这个表:
create table tbl(id varchar(2), val int);
insert into tbl values ('A', 1), ('B', 2), ('C', 3), ('D', 4), ('E', 5);
以下查询应该找出哪些记录集的值加起来不超过6(不重要的顺序):
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导致以下错误:
错误:ER_DATA_TOO_LONG:第7行的列
concat(id, '')
数据太长
为什么MySQL会产生这个错误?
有关信息,所需的输出如下:
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
我想知道MySQL在这里产生了这个错误(记录?)规则。
相比之下,查询在PostgreSQL和Oracle上运行正常(使用它们的语法变体),所以我真的不明白为什么MySQL有问题。
MySQL 8 CTE manual page的一个很长的路要走一个例子来说明你遇到的问题。基本上问题是你的ids
列太窄而不能分配给它的ABC
值,因为它从CTE的非递归部分得到它的宽度(实际上是id
的长度,即2个字符)。你可以用CAST
解决这个问题到足够大的宽度以适应所有结果,例如:
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