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
相关产品推荐
相关产品推荐

