问题
希望多次运行同一个查询,每次换入不同的值。
解决方案
用PD0::prepare()建立查询,然后在prepare()返回的已准备语句上调用execute()来运行这个查询。传入prepare()的查询中的占位符被execute()替换为具体的数据。
运行已准备语句
// 数据库连接信息
$user = 'admin'; // 数据库用户名
$password = '123456'; // 数据库密码
// 创建PDO实例,连接到MySQL数据库
$db = new PDO('mysql:host=127.0.0.1;port=3306;dbname=dvwa', $user, $password);
// 注意:这里没有设置错误模式为异常,但在实际应用中推荐这样做
// 例如:$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 准备SQL语句,使用?作为参数的占位符
// 这条语句的目的是从zodiac表中检索element列值为指定值的行的sign列
$st = $db->prepare('SELECT sign FROM zodiac where element LIKE ?');
// 执行SQL语句,并传递一个数组包含第一个参数的值('fire')
// LIKE查询通常需要通配符,但在这个例子中,我们假设element列的值直接匹配'fire'
// 若要匹配包含'fire'的任意文本,应使用'%fire%'作为值的一部分
$st->execute(array('fire'));
// 使用fetch()方法循环获取查询结果
// fetch()每次调用都会返回结果集中的下一行,直到没有更多行为止
while($row = $st->fetch()){
// $row是一个关联数组,键是列名,值是该列的数据
// 但由于我们只选择了一个列(sign),所以也可以使用索引数组访问
// $row[0]获取的是第一列(即sign列)的值
print $row[0] . "
"; // 输出sign列的值,并在每个值后添加换行符
}
// 再次执行相同的SQL语句,但这次传递的参数是'water'
// 注意:这里没有重新准备语句,因为我们已经使用prepare()方法准备好了
// 只需要改变传递给execute()方法的参数值即可
$st->execute(array('water'));
// 同样地,循环获取并输出查询结果
while($row = $st->fetch()){
print $row[0] . "
"; // 输出与'water'元素匹配的sign列的值
}
传入execute()的值称为绑定参数,每个值都与查询中的一个占位符关联(或“绑定”)。绑定参数的两大优点是安全和速度。利用绑定参数,不用再担心SQL注入攻击。PDO会适当地对各个参数加引号和进行转义,使特殊字符“中性化”。另外,执行prepare()时,很多数据库后端会完成查询的一些解析和优化,使得每个execute()调用要比你自行建立一个查询字符串来调用exec()或query()速度更快。