prepare() 执行后查不到数据,是因为它只编译不执行,必须调用 execute() 才真正发送sql;参数绑定需在 execute() 前完成,且 pdo 默认错误静默,应设 errmode_exception 才暴露问题。

为什么 prepare() 执行后查不到数据?
不是语句写错了,大概率是没调用 execute() —— prepare() 只编译不执行。PDO 和 MySQLi 都一样,返回的是一个语句对象,必须显式触发执行才能真正发往数据库。
-
prepare()返回PDOStatement或mysqli_stmt,此时 SQL 还没运行 - 参数绑定(
bind_param()或bindValue())必须在execute()之前完成 - 若跳过
execute()直接读fetch(),会得到空结果或警告Warning: PDOStatement::fetch(): SQLSTATE[HY000]: General error
MySQLi 中 bind_param() 的类型字符怎么记?
只记四个常用: i(整数)、d(浮点)、s(字符串)、b(大对象/BLOB)。别用 string 或 int 这类单词——那是错的,bind_param() 第一个参数必须是字符串字面量,且每个字符严格对应后续变量类型。
-
$stmt->bind_param('is', $id, $name)表示:第一个参数是整型,第二个是字符串 - 变量必须传引用(
&$id),否则报Warning: Parameter must be passed by reference - 如果传了 null 或未初始化变量,绑定会静默失败,查不到数据但无报错
PDO 的 prepare() 默认不报错,怎么让它暴露问题?
默认 PDO::ATTR_ERRMODE 是 PDO::ERRMODE_SILENT,错误被吞掉。改成 PDO::ERRMODE_EXCEPTION 才能在 prepare 失败时抛出异常,比如表名拼错、占位符语法错误(如写成 :name: 多了个冒号)。
- 连接时设置:
new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]) - 或连接后设置:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) - 注意:
prepare()报错 ≠ SQL 语法错,也可能是权限不足、表不存在、甚至字符集不匹配(如用utf8mb4连接却建了utf8表)
预处理真能防 SQL 注入?关键在哪儿?
能防,但前提是**所有动态值都走参数绑定**。只要有一个值拼进 SQL 字符串(比如表名、字段名、ORDER BY 条件),预处理就完全失效。
- 安全写法:
SELECT * FROM users WHERE status = ?+execute([$status]) - 危险写法:
"SELECT * FROM $table WHERE id = ?"——$table是用户输入,拼接即漏洞 - 动态表名/排序字段等必须白名单校验,例如:
in_array($order, ['created_at', 'name'], true) ? $order : 'id'
预编译的本质是服务端把 SQL 结构和数据分开处理,客户端传来的参数永远不会被当 SQL 解析——这个分离动作只发生在绑定值上,不在字符串拼接部分。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











