MySQL 截断 GROUP_CONCAT 函数的连接结果

Posted

技术标签:

【中文标题】MySQL 截断 GROUP_CONCAT 函数的连接结果【英文标题】:MySQL truncates concatenated result of a GROUP_CONCAT function 【发布时间】:2015-06-14 00:45:49 【问题描述】:

我创建了一个视图,它使用GROUP_CONCAT 将数据类型为'varchar(7) utf8_general_ci' 的产品列的查询结果连接到名为concat_products 的列中。

问题是 mysql 截断了“concat_products”列的值。 phpMyAdmin 说“concat_products”列的数据类型是varchar(341) utf8_bin

餐桌产品:

CREATE TABLE `products`(
    `productId` tinyint(2) unsigned NOT NULL AUTO_INCREMENT, 
    `product` varchar(7) COLLATE utf8_general_ci NOT NULL, 
    `price` mediumint(5) unsigned NOT NULL, 
    PRIMARY KEY (`productId`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci

“concat_products_vw”视图:

CREATE VIEW concat_products_vw AS
SELECT
  `userId`,
    GROUP_CONCAT(CONCAT_WS('_', `product`, `productId`, `price`) 
        ORDER BY `productId` ASC SEPARATOR '*') AS concat_products
FROM
  `users`
LEFT JOIN `products` 
ON `users`.`accountBalance` >= `product`.`price`
GROUP BY `productId` 

根据 MySQL 手册:

VARCHAR 列中的值是可变长度字符串 在 MySQL 4.0.2 之前,长度可以指定为 1 到 255 之间的值,在 MySQL 4.0.2 之前可以指定为 0 到 255。


编辑

Values in VARCHAR columns are variable-length strings. The length can be specified as a value from 0 to 65,535.

    为什么 MySQL 为 varchar "concat_products" 列指定超过 255 个字符? (已解决!)

    为什么是uf8_bin 而不是utf8_general_ci

    是否可以将视图中列的数据类型更改为“concat_products”列的文本?

    如果不能,我该怎么做才能防止 MySQL 截断“concat_products”列?

【问题讨论】:

你用的是什么版本的 MySQL? 仔细检查您的来源。 MySQL manual 说:VARCHAR 列中的值是可变长度字符串。长度可以指定为 0 到 65,535 之间的值。 @Jocelyn 你是对的,如果 mysql 可以在 varchar 列中存储多达 65535 个字符,为什么还要在这里截断? 【参考方案1】:

正如我在之前的评论中所写,MySQL manual 说:

VARCHAR 列中的值是可变长度字符串。长度可以 指定为 0 到 65,535 之间的值。

所以问题不在于字段的数据类型。

MySQL manual 还说:

结果被截断为由 group_concat_max_len 系统变量,默认值为 1024.该值可以设置得更高,虽然返回值的有效最大长度受值的限制 最大允许数据包。改变值的语法 运行时的 group_concat_max_len 如下,其中 val 是 无符号整数: 设置 [全球 |会话] group_concat_max_len = val;

您更改 group_concat_max_len 值的选项是:

    在 MySQL 启动时通过将其附加到以下命令来更改值:--group_concat_max_len=your_value_here 在您的 MySQL 配置文件 (mysql.ini) 中添加这一行:group_concat_max_len=your_value_here 在 MySQL 启动后运行此命令:SET GLOBAL group_concat_max_len=your_value_here; 打开 MySQL 连接后运行此命令:SET SESSION group_concat_max_len=your_value_here;

文档:SET、Server System Variables: group_concat_max_len

【讨论】:

感谢 mysql 不再截断 concat_products 列 我个人使用我列出的第 4 个选项,因为我的脚本中只有少数需要计算“大”GROUP_CONCAT,而且这些脚本并不经常运行。【参考方案2】:

正如 Jocelyn 提到的,GROUP_CONCAT() 结果的大小受group_concat_max_len 的限制,但是与ORDER BY 的额外交互导致进一步截断为group_concat_max_len 的1/3。示例见this related answer。

group_concat_max_len 的默认值为 1024,而 1024 / 3 = 341 可能解释了为什么 concat_products 的类型在原始示例中显示为 varchar(341)。如果您要删除 GROUP BY productId 子句,concat_products 应该显示为 varchar(1024)

我没有发现MySQL Manual中提到的GROUP_CONCAT()ORDER BY之间的这种交互,但它至少会影响MySQL Server 5.1。

【讨论】:

以上是关于MySQL 截断 GROUP_CONCAT 函数的连接结果的主要内容,如果未能解决你的问题,请参考以下文章

group_concat 函数长度限制解决

关于group_concat函数拼接字符超长的问题

MySQL GROUP_CONCAT长度限制引发的一场灾难

MySQL如何防止字符串截断[重复]

mysql GROUP_CONCAT 长度被限制

MySQL GROUP_CONCAT 砍掉一半的数据(有时)