反引号 `
(backtick) 与单引号 '
(single quote) 以及双引号 "
(double quote) 在 PHP 及 MySQL 中都有不同的含义,下面将分别说明并给出它们在 PHP 和 MySQL 结合使用时的一些注意事项。
`
在 PHP 中是 执行运算符 ,效果与调用 shell_exec() 相同 。
'
在 PHP 中用来输出字面量值,被单引号括起来的内容会被原样输出。
"
在 PHP 中可以用来解析变量。
`
被用来在查询,告诉解析器反引号内的内容表示一个字面量,直接读取而不用做变量替换。
"
与 '
用来均被用来解析 MySQL 字符串及 特殊字符 ,不过这与 MySQL 的 SQL mode 设置有关。当 ANSI_QUOTES
开启时, "
将被当作标识符。
MySQL 中开启 ANSI mode 时将会使用 '
来告诉解析器, '
内包裹的字符串字面量直接读取,无需解析。
mysql> SET SESSION sql_mode ='ANSI_QUOTES';
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo','/'hello','/r';
+-------+---------+-----------+--------+--------+---+
| hello | "hello" | ""hello"" | hel'lo |'hello | |
+-------+---------+-----------+--------+--------+---+
|hello | "hello" | ""hello"" | hel'lo |'hello |
+-------+---------+-----------+--------+--------+---+
1 row in set (0.01 sec)
mysql> SELECT "hello", '"hello"', '""hello""', 'hel''lo','/'hello','/r';
ERROR 1054 (42S22): Unknown column 'hello' in 'field list'
mysql> SELECT hello, '"hello"', '""hello""', 'hel''lo','/'hello','/r';
ERROR 1054 (42S22): Unknown column 'hello' in 'field list'
mysql> SELECT `hello`, '"hello"', '""hello""', 'hel''lo','/'hello','/r';
ERROR 1054 (42S22): Unknown column 'hello' in 'field list'
为了防止 SQL 注入,最好使用预处理语句及参数绑定来执行查询。建议使用 PDO 或者 MySQLi
PDO
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
MySQLi
<?php
$mysqli = new mysqli("localhost", "user", "password", "database");
$stmt = $mysqli->prepare("INSERT INTO `test`(`id`) VALUES (?)");
$stmt->bind_param("i", $id)
SQL 标准规定使用 '
来包裹字符串,但不同的数据库有不同的实现,最好的方式,当然是使用 PDO ,这样就不用对 sql 语句单独进行处理,而且在转换数据库时业务逻辑中的 sql 也无需修改和转换。
最好的实践其实应该在代码设计上规避错误:
SELECT @@sql_mode
`
包裹表名及列名 '
包裹查询条件