原地址:https://www.cnblogs.com/mafeng/p/6306096.html
参数化查询 (Parameterized Query 或 Parameterized Statement) 是指在设计与数据库连接并访问数据时,在需要填写数值或数据的地方,使用参数(Parameter)来给值,这个方法目前已被视为最有效可预防SQL注入攻击(SQL Injection) 的攻击手法的防御方式。有部分的开发人员可能会认为使用参数化查询,会让程序更不好维护,或者在实现部分功能上会非常不便[来源请求],然而,使用参数化查询造成的额外开发成本,通常都远低于因为SQL注入攻击漏洞被发现而遭受攻击,所造成的重大损失。
除了安全因素,相比起拼接字符串的SQL语句,参数化的查询往往有性能优势。因为,参数化的查询能让不同的数据通过参数到达数据库,从而公用一条SQL语句。大多数数据库会缓存解释SQL语句产生的字节码而省下重复解析的开销。如果采用拼接字符串的SQL语句,则会用于操作数据是SQL语句的一部分而非参数的一部分,而反复大量解释SQL语句产生不必要的开销。
MySQL的参数格式是以 "?" 字符加上参数名称而成。
UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4
1、PDO
PDO用于PHP之内。在使用PDO驱动时,参数查询的使用方法一般为:
// 实例化数据抽象层对象
$db = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=testdb');
// 对 SQL 语句执行prepare,得到PDOStatement对象$stmt = $db->prepare('SELECT * FROM myTable WHERE "id" = :id AND "is_valid" = :is_valid');
// 绑定参数
$stmt->bindValue(':id',$id);
$stmt->bindValue(':is_valid',true);
// 查询
$stmt->execute();
// 获取数据
froeacha($stmt as $row){ var_dump($row); }
2、Mysqli
$db = new mysqli("localhost","user","pass","database");
$stmt = $db->prepare("SELECT priv FROM testUsers WHERE username=? AND password=?");
$stmt->bind_param("ss",$user,$pass);
$stmt->execute();
3、mysql_real_escape_string
值得注意的是,以下方式虽然能有效防止SQL注入 (归功于 mysql_real_escape_string 函数的转义),但并不是真正的参数化的查询,其本质仍然是拼接字符串的SQL语句。
$query = sprintf("SELECT * FROM user WHERE username='%s' AND password='%s',mysql_real_escape_string($username),mysql_real_escape_string($password)");
$mysql_query($query);