预处理语句对于防止 MySQL 注入是非常有用的。使用预准备语句可提高重复使用语句的性能,在PHP中,使用prepare()方法来进行预准备语句查询,使用execute()方法来执行预准备语句。PHP有两种预准备语句:一种是绑定结果,另一种是绑定参数。
预处理语句, 绑定参数及绑定结果
预处理语句用于执行多个相同的 SQL 语句,并且执行效率更高。
预处理语句的工作原理如下:
预处理:创建 SQL 语句模板并发送到数据库。预留的值使用参数 "?" 标记 。例如:
INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)
数据库解析,编译,对SQL语句模板执行查询优化,并存储结果不输出。
执行:最后,将应用绑定的值传递给参数("?" 标记),数据库执行语句。应用可以多次执行语句,如果参数的值不一样。
相比于直接执行SQL语句,预处理语句有两个主要优点:
预处理语句大大减少了分析时间,只做了一次查询(虽然语句多次执行)。
绑定参数减少了服务器带宽,你只需要发送查询的参数,而不是整个语句。
预处理语句针对SQL注入是非常有用的,因为参数值发送后使用不同的协议,保证了数据的合法性。
MySQLi 预处理语句及绑定参数
所谓绑定参数就是把PHP脚本中的自定义变量绑定到SQL语句中的参数(参数使用 “?”代替)上,绑定参数使用bind_param()方法,该方法的语法格式如下:
bool bind_param ( string $types , mixed &$var1 [, mixed &$... ] )
以下实例在 MySQLi 中使用了预处理语句,并绑定了相应的参数:
$servername= "localhost";
$username= "username";
$password= "password";
$dbname= "ikeepstudying";//创建连接
$conn = newmysqli($servername, $username, $password, $dbname);//检测连接
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}//预处理及绑定
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);//设置参数并执行
$firstname = "John";
$lastname= "Doe";
$email= "john@example.com";
$stmt->execute();
$firstname= "Mary";
$lastname= "Moe";
$email= "mary@example.com";
$stmt->execute();
$firstname= "Julie";
$lastname= "Dooley";
$email= "julie@example.com";
$stmt->execute();
echo"新记录插入成功";
$stmt->close();
$conn->close();?>
解析以下实例的每行代码:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"
在 SQL 语句中,我们使用了问号 (?),在此我们可以将问号替换为整型,字符串,双精度浮点型和布尔值。
接下来,让我们来看下 bind_param() 函数:
$stmt->bind_param("sss", $firstname, $lastname, $email);
该函数绑定了 SQL 的参数,且告诉数据库参数的值。 "sss" 参数列处理其余参数的数据类型。s 字符告诉数据库该参数为字符串。
types:绑定的变量的数据类型,它接受的字符种类包括4个,如表所示。
字符种类
代表的数据类型
i
integer
d
double
s
string
b
blob
参数types接受的字符的种类和绑定的变量需要一一对应。
通过告诉数据库参数的数据类型,可以降低 SQL 注入的风险。
注意: 如果你想插入其他数据(用户输入),对数据的验证是非常重要的。
MySQLi 预处理语句及绑定结果
所谓绑定结果就是把PHP脚本中的自定义变量绑定到结果集中的相应字段上,这些变量就代表着所查询的记录,绑定结果的示例代码如下:
$mysqli= new mysqli("localhost","root","root","ikeepstudying"); //实例化mysqli
$query = "select * from MyGuests";
$result= $mysqli->prepare($query); //进行预准备语句查询
$result->execute(); //执行预准备语句
$result->bind_result($id,$firstname,$lastname,$email); //绑定结果
while ($result->fetch()) {
echo $id;
echo $firstname;
echo $lastname;
echo $email;
}
$result->close(); //关闭预准备语句
?>
在绑定结果的时候,脚本中的变量要与结果集中的字段一一对应,绑定完以后,通过fetch()方法将绑定在结果集中的变量一一取出来,最后将预准备语句和数据库连接分别关闭。
MySQLi 同时绑定参数和绑定结果
在一个脚本中还可以同时绑定参数和绑定结果,示例代码如下:
$conn= new mysqli("localhost","root","root","ikeepstudying"); //实例化mysqli
$query = "select * from MyGuests where id < ?";
$result= $conn->prepare($query);
$result->bind_param("i",$id); //绑定参数
$id=4;
$result->execute();
$result->bind_result($id,$number,$name,$age); //绑定结果
while ($result->fetch()) {
echo $id;
echo $firstname;
echo $lastname;
echo $email;
}
$result->close();
$conn->close();?>
4. PHP MySQL 读取数据, 删除及更新
SELECT 语句用于从数据表中读取数据:
在mysqli中,执行查询使用query()方法,该方法的语法格式如下:
mixed query ( string $query [, int $resultmode ] )
在上述语法中涉及到的参数说明如下。
l query:向服务器发送的SQL语句。
l resultmode:该参数接受两个值,一个是MYSQLI_STORE_RESULT,表示结果作为缓冲集合返回;另一个是MYSQLI_USE_RESULT,表示结果作为非缓冲集合返回。
下面是使用query()方法执行查询的例子:
1.面向对象
$mysqli= new mysqli("localhost","root","root","ikeepstudying"); //实例化mysqli
$query = "select * from MyGuests";
$result= $mysqli->query($query);if($result) {if($result->num_rows>0){ //判断结果集中行的数目是否大于0
while($row = $result->fetch_array() ){ //循环输出结果集中的记录
echo ($row[0])."
";
echo ($row[1])."
";
echo ($row[2])."
";
echo ($row[3])."
";
echo"
";
}
}
}else{
echo"查询失败";
}
$result->free();
$mysqli->close();?>
在上面代码中,num_rows为结果集的一个属性,返回结果集中行的数目。方法fetch_array()将结果集中的记录放入一个数组中并将其返回。最后使用free()方法将结果集中的内存释放,使用close()方法将数据库连接关闭。
对于删除记录(delete)、保存记录(insert)和修改记录(update)的操作,也是使用query()方法来执行的,下面是删除记录的例子: