联合中的MySQL组_concat(utf8)被截断为1024/3
TLDR:联合中的MySQL组_concat(utf8)被截断为1024/3,mysql,group-concat,Mysql,Group Concat,TLDR:group\u concat(utf8 varchar)联合本身仅返回group\u concat\u max\u len/3ASCII字符,就好像字符长度是固定的而不是可变的一样。 group\u concat单独返回group\u concat\u max\u len字符 问题 我有一个表tabletest,其中一列data定义为UTF8 varchar(2048)。 表中只有一行,列中有1050个ASCII字符 此表/列上的group\u concat返回1024个字符(等于gr
group\u concat(utf8 varchar)联合本身
仅返回group\u concat\u max\u len/3
ASCII字符,就好像字符长度是固定的而不是可变的一样。
group\u concat
单独返回group\u concat\u max\u len
字符
问题
我有一个表tabletest
,其中一列data
定义为UTF8 varchar(2048)
。
表中只有一行,列中有1050个ASCII字符
此表/列上的group\u concat
返回1024个字符(等于group\u concat\u max\u len
),这是预期的
但此组concat
与相同的组concat
的并集返回341个字符(等于组concat\u max\u len/3
)
为什么会发生这种情况
根据:
结果类型为TEXT或BLOB,除非group_concat_max_len小于或等于512,在这种情况下,结果类型为VARCHAR或VARBINARY
和来自:
类似地,可以将文本列视为VARCHAR列。BLOB和TEXT与VARBINARY和VARCHAR的区别如下:
- 对于BLOB和TEXT列上的索引,必须指定索引前缀长度。对于CHAR和VARCHAR,前缀长度是可选的。见第8.3.4节“列索引”
- BLOB和TEXT列不能具有默认值
TEXT
,它也是可变长度的,并且应该支持utf8中的ASCII字符,宽度为1字节
承认问题的相关答案
可能的罪犯
同样来自:
排序时仅使用列的第一个最大排序长度字节。最大排序长度的默认值为1024
AFAIKUNION
需要在消除重复项之前对行进行排序,因此这似乎是一个可能的原因。但通过设置max\u sort\u length=2048进行更改代码>未更改返回的字符数
唯一的解决办法似乎是SET group_concat_max_len=1539代码>或更多。仅1538或更少返回512或更少字符。为什么是这个奇怪的数字
完整示例
create database uniontest collate utf8_general_ci;
create table uniontest.tabletest (data varchar(2048));
insert into uniontest.tabletest select repeat('a',1050);
简单选择1050个字符的长度:
select length(data) from uniontest.tabletest;
产出:
+--------------+
| length(data) |
+--------------+
| 1050 |
+--------------+
对1050个字符的单行进行分组(因此不添加分隔符)。在服务器配置组中\u concat\u max\u len=1024
输出按预期截断:
+------------------------------------------+
| length(group_concat(data separator ',')) |
+------------------------------------------+
| 1024 |
+------------------------------------------+
现在与自身联合(试图防止额外的数据类型转换):
意外结果(应为1024):
在MySQL 5.6和5.7上测试
编辑
发现了一个关于ORDER BY
而不是UNION
的错误报告。报告已关闭,可能只有
ORDER BY
案例已修复?其他一些奇怪的结果:
+------------------------------------------+
| length(group_concat(data separator ',')) |
+------------------------------------------+
| 1024 |
+------------------------------------------+
select length(data) from (
select group_concat(data separator ',') as data from uniontest.tabletest union
select group_concat(data separator ',') as data from uniontest.tabletest) d;
+--------------+
| length(data) |
+--------------+
| 341 |
+--------------+