PHP使用bind_param结合STR_TO_DATE执行SQL更新失败问题
问题根源
你的代码执行失败核心有两个错误:
- 预处理语句的
?占位符被包裹在了单引号内部,SQL解析时会把引号内的内容判定为普通字符串字面量,不会识别为需要绑定参数的占位符。你写的' ?, ?, ? '在预处理阶段只会被当成包含三个问号的普通字符串,最终整个SQL里只有WHERE UserName=?这1个有效占位符,但你调用bind_param时传入了4个参数,参数数量不匹配会直接导致执行失败。 STR_TO_DATE()函数的用法错误,该函数第一个参数要求传入完整的待解析日期字符串,你把三个占位符拆开放在引号里的写法,就算手动替换值能跑,也是因为刚好拼成了符合要求的字符串,本身不符合函数的调用逻辑。
你手动把?替换成实际值能执行成功,是因为直接拼接后引号内的内容变成了类似'01,10,2024'的合法日期字符串,绕过了预处理阶段占位符识别的问题,但这种写法有SQL注入风险,完全不推荐。
修复后的正确代码
不要给占位符加任何引号,用CONCAT()函数把你传入的日、月、年三个参数拼成日,月,年格式的完整字符串,再传给STR_TO_DATE做日期解析即可:
// 所有?占位符均独立存在,不被引号包裹 $sqlUpdate3 = $connection->prepare("UPDATE Users SET DateOfBirth = STR_TO_DATE(CONCAT(?, ',', ?, ',', ?), '%d,%m,%Y') WHERE UserName=?"); // 4个参数均按顺序绑定,类型字符串ssss对应四个字符串类型入参 $sqlUpdate3->bind_param("ssss", $_POST["daySelect"], $_POST["monthSelect"], $_POST["yearSelect"], $_SESSION["username"]); $sqlUpdate3->execute();
注意事项
- 所有预处理占位符都不能放在单引号、双引号内部,不管绑定的参数是字符串、日期还是数字类型,数据库驱动会自动完成类型处理和转义,手动给占位符加引号反而会导致占位符失效
- 占位符只能用于替换值,不能用来拼接表名、列名、SQL关键字这类语法元素
- 执行更新操作后建议调用
$sqlUpdate3->affected_rows检查实际更新的行数,方便排查逻辑问题
内容的提问来源于stack exchange,提问作者Diogo Carvalho
相关产品推荐
相关产品推荐

