使用PDO更新MySQL JSON列时值被转为字符串如何解决?
问题根因
PDO默认调用execute()传入关联数组时,所有参数都会被按字符串类型(PDO::PARAM_STR)处理,传入的数值1会被转为字符串'1'绑定到SQL中,因此JSON_OBJECT生成的字段值就是字符串类型。直接写SQL字面量时1会被MySQL识别为数值类型,所以结果符合预期。
解决方案
方案1:显式绑定参数并指定类型
不直接通过execute()传参数数组,改用bindValue方法手动指定参数类型,适合value类型固定为整数的场景:
$data['id'] = 1; $data['key'] = 'new_field'; $data['value'] = 1; $query= " UPDATE `table` SET `data` = JSON_MERGE_PATCH(`data`, JSON_OBJECT(:key, :value)) WHERE `id` = :id "; $stmt = $pdo->prepare($query); $stmt->bindValue(':key', $data['key'], PDO::PARAM_STR); $stmt->bindValue(':value', $data['value'], PDO::PARAM_INT); // 明确指定为整数类型 $stmt->bindValue(':id', $data['id'], PDO::PARAM_INT); $stmt->execute();
方案2:SQL层面显式转换类型
如果不想修改PHP绑定逻辑,可以直接在SQL中对value参数做类型转换:
UPDATE `table` SET `data` = JSON_MERGE_PATCH(`data`, JSON_OBJECT(:key, CAST(:value AS UNSIGNED))) WHERE `id` = :id
如果value为浮点类型,可将UNSIGNED替换为DOUBLE/DECIMAL等对应数值类型。
方案3:PHP侧预生成JSON补丁(推荐,适配所有类型)
直接在PHP侧构造要合并的键值对结构,通过json_encode保留原始数据类型后传入SQL,适合value类型不固定、或需要同时修改多个JSON字段的场景:
$data['id'] = 1; $data['key'] = 'new_field'; $data['value'] = 1; // 构造要合并的JSON片段 $patch = [ $data['key'] => $data['value'] ]; $jsonPatch = json_encode($patch); $query= " UPDATE `table` SET `data` = JSON_MERGE_PATCH(`data`, CAST(:json_patch AS JSON)) WHERE `id` = :id "; $stmt = $pdo->prepare($query); $stmt->execute([ 'json_patch' => $jsonPatch, 'id' => $data['id'] ]);
补充说明:如果以上方案仍有异常,可关闭PDO模拟预处理避免额外类型转换:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
内容的提问来源于stack exchange,提问作者user16461680
相关产品推荐
相关产品推荐

