You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),因此触发字符串格式错误。

具体修正步骤

  1. 显式指定二进制参数类型
    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();
    
  2. 修正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字段是否有变化。

  3. 统一用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:24:55