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

PDO调用JSON_INSERT更新MySQL JSON字段报错如何解决

错误原因

致命错误:未捕获的PDOException:SQLSTATE[22032]: <>: 3140 无效的JSON文本:列'products.p_description'对应值在位置1处「缺少对象成员名称」。

这个错误的核心诱因是两点:

  • 你把MySQL内置函数JSON_INSERT作为普通字符串值传入PDO参数绑定逻辑,PDO会自动对所有绑定的字符串值做转义加引号处理,最终执行的SQL实际效果为UPDATE products SET p_description = 'JSON_INSERT(p_description , \'$.chipset\' , \'Qualcomm\')' WHERE id = 1,相当于你试图把JSON_INSERT开头的普通字符串存入JSON类型字段,该字符串不符合JSON格式要求,因此触发非法JSON文本报错。
  • 你封装的update方法本身设计只支持字段值为普通数据的场景,所有传入的字段值都会被拼接成字段名 = :参数名的模板,本身不支持传入SQL函数作为字段更新值。
修复方案

方案1:修改CRUD类的update方法,支持SQL函数表达式更新

调整update方法逻辑,新增SQL表达式的识别规则,避免把函数表达式当成普通参数绑定:

public function update($table, $fields = [], $where = null)
{
    $args    = [];
    $this->bindParams = []; // 新增类属性存储需要绑定的参数
    foreach ($fields as $fk => $fv) :
        $fk = $this->strSafe($fk);
        // 约定:值为数组且包含expr键时,视为SQL表达式直接拼接
        if (is_array($fv) && isset($fv['expr'])) {
            $args[] = $fk . ' = ' . $fv['expr'];
            if (isset($fv['params']) && is_array($fv['params'])) {
                $this->bindParams = array_merge($this->bindParams, $fv['params']);
            }
        } else {
            $args[] = $fk . ' = :' . $fk;
            $this->bindParams[':'.$fk] = $fv;
        }
    endforeach;

    $sql = 'UPDATE ' . $table . ' SET ' . implode(', ', $args);

    if ($where != null) {
        $sql .= ' WHERE ' . $where;
    }

    $this->sql = $sql;
    return $this->sql;
}

调用时按约定传值即可:

$upMemList = [
    'p_description' => [
        'expr' => "JSON_INSERT(`p_description` , '$.chipset' , ?)",
        'params' => ['Qualcomm']
    ]
];
$upOn = $dbh->update('products', $upMemList, 'id = ?');
$dbh->prepare($upOn);
// 按顺序绑定参数即可
$dbh->bind(1, 'Qualcomm');
$dbh->bind(2, 1);
$dbh->execute();

方案2:无需修改封装类,PHP侧处理JSON后更新

如果不想调整现有CRUD封装,可以先查询出原JSON字段内容,在PHP侧新增属性后再回写:

// 查询现有JSON数据
$product = $dbh->query("SELECT p_description FROM products WHERE id = 1")->fetch(PDO::FETCH_ASSOC);
$desc = json_decode($product['p_description'], true);
// 新增属性
$desc['chipset'] = 'Qualcomm';
// 执行更新
$upMemList = [
    'p_description' => json_encode($desc)
];
$upOn = $dbh->update('products', $upMemList, 'id = :id');
$dbh->prepare($upOn);
$dbh->bind(':p_description', json_encode($desc));
$dbh->bind(':id', 1);
$dbh->execute();

内容的提问来源于stack exchange,提问作者Fred

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:30:01