PHP注释在SQL中无效,MySQL仅识别--(后跟空格)、#、/ /三种注释;防注入唯一可靠方式是参数化查询,禁用字符串拼接。

SQL 语句里写 PHP 注释根本没用
PHP 的 // 或 /* */ 注释只在 PHP 解析器执行时起作用,一旦拼接到 SQL 字符串里发给数据库,这些注释就变成普通文本——MySQL、PostgreSQL 等压根不认 PHP 风格的注释。更危险的是,如果用户输入里混进 --、# 或 /* */,反而可能被数据库当真,干扰原有逻辑甚至绕过条件检查。
MySQL 支持的合法 SQL 注释语法只有三种
真正能被 MySQL 执行器识别并忽略的注释,必须符合其协议规范:
-
--(注意后面必须跟一个空格):单行注释,从--开始到行尾 -
#:单行注释,从#开始到行尾(仅 MySQL 支持,非标准 SQL) -
/* ... */:多行注释,但不能嵌套;若写成/*! ... */,MySQL 会执行其中内容(用于条件兼容性指令)
例如这段 SQL 是有效的:
SELECT id, name FROM users WHERE status = 1 -- 过滤启用状态 AND deleted = 0; /* 跳过回收站数据 */
想“注释掉”SQL 片段?别手拼,用参数化或条件组装
开发中常想临时禁用某段 WHERE 条件,比如把 AND created_at > '2024-01-01' 注释掉。手动加 -- 极易出错,且容易遗留测试代码到生产。正确做法是让 PHP 控制逻辑分支:
立即学习“PHP免费学习笔记(深入)”;
- 用布尔变量控制是否追加条件:
if ($needDateFilter) { $sql .= " AND created_at > ?"; } - 使用 PDO/MySQLi 的预处理语句,把值绑定进去,而非字符串拼接
- 避免用
mysql_real_escape_string(已废弃)或简单addslashes()做“防注入”,它们对注释类攻击无效
错误示范(看似注释,实则危险):
$sql = "SELECT * FROM posts WHERE id = " . $_GET['id'] . " -- "; // 用户传入 id=1 OR 1=1 /* 就会闭合注释! */
真正的防注入只靠参数化,和注释无关
SQL 注释本身不是安全机制,也不是防注入手段。所谓“用注释防注入”是典型误解。唯一可靠的方式是彻底分离 SQL 结构与数据:
- PDO:用
prepare()+bindValue()或问号占位符 - MySQLi:用
prepare()+bind_param() - 绝不把用户输入直接拼进 SQL 字符串,无论你加了多少
--或#
哪怕你写满十行 -- 注释,只要用户输入进了字符串拼接,就可能破坏 SQL 结构。注释只是写给人看的,数据库只信语法树。
最常被忽略的一点:ORM 或查询构建器(如 Laravel Query Builder、Doctrine DBAL)默认启用参数化,但一旦调用 whereRaw()、DB::raw() 或拼接 CONCAT() 类函数,就退回高危模式——那里才是注释真正该消失的地方。











