MySQL MEDIUMBLOB插入图片数据报HY000 1366错误的解决咨询
问题描述
尝试通过file_get_contents($imageURL)获取图片二进制数据,插入到MySQL表的mediumblob列(该列为新增列,表中此前无图片数据),执行UPDATE预处理语句时触发错误:
(HY000,1366,Incorrect string value: '\xFF\xD8\xFF\xE0\x00\x10...' for column 'newImage' at row 1)
实际执行的等效SQL语句:
WITH newValues AS ( SELECT 'UCmwUfKjS6zDt_kHTTMw9Rig' AS channelId , <data> AS newImage , 'https://yt3.ggpht.com/yada/yada' AS newImageURL ) UPDATE AuthorChannels ac JOIN newValues nv ON ac.channel_id = nv.channelId SET ac.image = nv.newImage , ac.imageURL = nv.newImageURL WHERE ac.image != nv.newImage OR COALESCE(ac.imageURL, '') <> COALESCE(nv.newImageURL, '') ;
相关PHP代码:
$newImage = (empty($img_url) ? '' : @file_get_contents($img_url)) ; $authorChannelValues = [ 'channelId' => $channelId , 'image' => empty($newImage) ? NULL : $newImage , 'imgurl' => empty($img_url) ? NULL : $img_url ] ; $ok = $insertAuthorChannel->execute($authorChannelValues) ;
原始SQL预处理语句:
WITH newValues AS ( SELECT :channelId AS channelId , :image AS newImage , :imgurl AS newImageURL ) UPDATE AuthorChannels ac JOIN newValues nv ON ac.channel_id = nv.channelId SET ac.image = nv.newImage , ac.imageURL = nv.newImageURL WHERE ac.image != nv.newImage OR COALESCE(ac.imageURL, '') <> COALESCE(nv.newImageURL, '')
表结构:
mysql> describe AuthorChannels; +-------------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | channel_id | varchar(32) | YES | MUL | NULL | | | firstChatEpoch | int | YES | | NULL | | | lastChatEpoch | int | YES | | NULL | | | chatCount | int | YES | | NULL | | | firstCommentEpoch | int | YES | | NULL | | | lastCommentEpoch | int | YES | | NULL | | | commentCount | int | YES | | NULL | | | doNotList | tinyint | NO | | 0 | | | image | mediumblob | YES | | NULL | | | imageURL | varchar(255) | YES | | NULL | | +-------------------+--------------+------+-----+---------+----------------+
疑惑:明明是BLOB字段,为何会把二进制图片数据判定为无效字符串?该如何解决?
解决方案
核心原因
虽然image列定义为mediumblob,但预处理时默认把二进制数据当作字符串类型绑定,而数据库连接的字符集(如utf8、utf8mb4)无法解析图片中的非UTF-8字节(比如\xFF),因此触发字符串格式错误。
具体修正步骤
显式指定二进制参数类型
PHP的PDO中,直接用execute()传数组会把所有参数默认按字符串处理,必须用bindParam显式指定image参数为PDO::PARAM_LOB(大对象类型,对应BLOB)。修改PHP代码:$newImage = empty($img_url) ? null : @file_get_contents($img_url); $authorChannelValues = [ 'channelId' => $channelId, 'image' => $newImage, 'imgurl' => empty($img_url) ? null : $img_url ]; // 绑定参数并指定类型 $insertAuthorChannel->bindParam(':channelId', $authorChannelValues['channelId'], PDO::PARAM_STR); $insertAuthorChannel->bindParam(':image', $authorChannelValues['image'], PDO::PARAM_LOB); $insertAuthorChannel->bindParam(':imgurl', $authorChannelValues['imgurl'], PDO::PARAM_STR); $ok = $insertAuthorChannel->execute();修正BLOB字段的比较逻辑
原SQL中ac.image != nv.newImage的写法不适用于BLOB类型,因为BLOB是二进制数据,直接用!=可能出现异常,建议改为:WHERE ac.image IS DISTINCT FROM nv.newImage OR COALESCE(ac.imageURL, '') <> COALESCE(nv.newImageURL, '')IS DISTINCT FROM支持NULL值的比较,能准确判断BLOB字段是否有变化。统一用NULL表示无图片数据
原代码中为空时赋值空字符串'',但BLOB字段更适合用NULL表示无数据,避免存储无效的字符串二进制:$newImage = empty($img_url) ? null : @file_get_contents($img_url);
额外排查点
- 去掉
file_get_contents前的@错误抑制符,临时添加日志确认图片是否成功获取:if (!empty($img_url)) { $newImage = file_get_contents($img_url); if ($newImage === false) { error_log("无法获取图片:$img_url"); $newImage = null; } } else { $newImage = null; } - 确认数据库连接字符集设置不影响BLOB操作:BLOB本身不依赖字符集,但显式指定
PARAM_LOB可以避免连接字符集对二进制数据的转码。
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

