PDO提供了一种名为预处理语句的机制,它可以将整个SQL命令向数据库服务器发送一次。以后只有参数发生变化,数据库服务器只需对命令的结构做一次分析就够了,即编译一次,可以多次执行。会在服务器上缓存查询的语句和执行过程,而只在服务器和客户端之间传输有变化的列植,以此来消除这些额外的开销。不仅可以减少需要传输的数据量,还提高了命令的处理效率。可以有效防止SQL注入,在执行单个查询时快于直接使用query()/exec()的方法,速度快而且安全。
1. PDOStatement对象
PDOStatement对象是由PDO对象中的prepare()方法,在数据库服务器中准备好一个预处理的SQL语句后直接返回的。PDO对象中的query()方法返回的PDOStatement类对象,只代表的是一个结果集对象。而如果通过执行PDO对象中的prepare()方法产生的PDOStatement类对象,则为一个查询对象,能定义和执行参数化的SQL命令。
方法名 | 描述 |
---|---|
bindColumn() | 用来匹配列名和一个特定的变量名,这样每次获取各行记录时,会自动将相应的列值赋给该变量 |
bindParam() | 将参数绑定到相应的查询占位符上 |
bindValue() | 将一值绑定到对应的一个参数中 |
closeCursor() | 关闭游标,使该声明再次被执行 |
columnCount() | 在结果集中返回列的数目 |
errorCode() | 获取错误码 |
errorInfo() | 获取错误的信息 |
execute() | 负责执行一个准备好的预处理查询 |
fetch() | 返回结果集的下一行,当到达结果集末尾时返回false |
fetchAll() | 通过一次调用就可以获取结果集中的所有行,并赋值给返回的数组 |
fetchColumn() | 返回结果集中下一行某个列的值 |
fetchObject() | 获取下一行记录并返回它作为一个对象 |
getAttribute() | 获取一个声明属性 |
getColumnMeta() | 在结果集中返回某一列的属性信息 |
nextRowset() | 检索下一行集(结果集) |
rowCount() | 返回执行DQL语句后查询结果的记录行数,或返回执行DML语句后受影的记录行总数 |
setAttribute() | 为一个预处理语句设置属性 |
setFetchMode() | 设置获取结果集合的类型 |
2. 准备语句
需要使用占位符号来替代需要使用变量作为值的地方。PDO中有两种使用占位符的语法:”命名参数”和”问号参数”
- 使用命名参数作为占位符的INSERT查询:
$dbh->prepare("INSERT INTO userInfo(name,address,phone) VALUES(:name,:address,:phone)")
- 需要自定义一个字符串作为”命名参数”,每个命名参数需要使用冒号(:)开始,参数的命名一定要有意义,最好和对应的字段名称相同
$dbh->prepare("INSERT INTO userInfo(name,address,phone) VALUES(?,?,?)")
问号参数一定要和字段的位置顺序相对应
3. 绑定参数
如果使用了占位符,就需要在每次执行时替换输入的参数。可以通过PDOStatement对象中的bindParam()方法,把参数变量绑定到准备好的占位符(位置和名字要对应)。
bindParam(mixed parameter, mixed &variable[,int data_type[,int length[,mixed driver_options]]])
第一个参数parameter是必选项,如果在准备好的查询中占位符语法使用名字参数,那么将名字参数字符串作为bindParam()方法的第一个参数提供。如果使用问号参数,那么将准备好的查询中列值占位符的索引偏移量,作为该方法的第一个参数提供。
第二个参数variable也是必选项,提供赋给第一个参数所指定占位符的值。因为该参数是按引用传递的,所以只能提供变量作为参数,不能直接提供数值。
第三个参数data_type是可选项,显示地为当前被绑定的参数设置数据类型。
- PDO::PARAM_BOOL:代表boolean数据类型
- PDO::PARAM_NULL:代表SQL中NULL类型
- PDO::PARAM_INT:代表SQL中INTEGER数据类型
- PDO::PARAM_STR:代表SQL中CHAR,VARCHAR和其他字符串数据类型
- PDO::PARAM_LOB:代表SQL中大对象数据类型
第四个参数length可选,用于指定数据类型的长度
- 第五个参数driver_options是可选项,通过该参数提供人任何数据库驱动程序特定的选项
<?php
//省略上面的内容
$query = "INSERT INTO userInfo(name, address, phone) VALUES(:name, :address, :phone)";
$stmt = $dbh->prepare($query); //调用PDO对象中的prepare()方法
//第二个参数需要按引用传递,所以 需要使用变量作为参数
$stmt->bindParam(':name', $name);
$stmt->bindParam(':address', $address);
$stmt->bindParam(':phone', $phone);
$name = "张某某";
$address = "北京海淀区中关村";
$phone = "18644444443";
使用问号参数的绑定示例如下所示。并在绑定时通过第三个参数显式地指定数据类型。
<?php
//省略上面的内容
$query = "INSERT INTO userInfo(name, address, phone) VALUES(?,?,?)";
$stmt = $dbh->prepare($query); //调用PDO对象中的prepare()方法
//第二个参数需要按引用传递,所以 需要使用变量作为参数
$stmt->bindParam(1, $name, PDO::PARAM_STR);
$stmt->bindParam(2, $address, PDO::PARAM_STR);
$stmt->bindParam(3, $phone, PDO::PARAM_STR, 20);
$name = "张某某";
$address = "北京海淀区中关村";
$phone = "18644444443";
4. 执行准备好的查询
使用PDOStatement类对象的execute()方法
<?php
try{
$dbh = new PDO('mysql:dbname=testdb;host=localhost', 'mysql_user', 'mysql_pwd');
}catch(PDOException $e){
echo "数据库连接失败:".$e->getMessage();
}
$query = "INSERT INTO contactInfo(name,address, phone) VALUES(?, ?, ?)";
$stmt = $dbh->prepare($query);//调用PDO对象中的prepare()方法准备查询
$stmt->bindParam(1, $name);
$stmt->bindParam(2,$address);
$stmt->bindParam(3,$phone);
$name="常某";
$address = "北京";
$phone = "18333333333";
$stmt->execute(); //执行参数被绑定后的准备语句
$name = "孙某某";
$address = "宣武区";
$phone = "15033333333";
$stmt->execute();//再次执行参数被绑定后的准备语句,插入第二条语句
通过使用execute()方法中提供一个可选参数,该参数是由准备查询中的命名参数占位符组成的数组,来替换输入的参数。
- 使用关联数组,这个关联数组的每个下标名称都要和命名参数名称一一对应(可以不用命名参数前缀”:”).
<?php
//省略上面的内容
$query = "INSERT INTO userInfo(name, address, phone) VALUES(:name, :address, :phone)";
$stmt = $dbh->prepare($query); //调用PDO对象中的prepare()方法
//传递一个数组为预处理查询中的命名参数绑定值,并执行一次
$stmt->execute(array(":name"=>"赵某某",":address"=>"海淀区",":phone"=>"15333333333"));
//再次传递一个数组为预处理查询中的命名参数绑定值,并执行第二次插入数据
$stmt->execute(array(":name"=>"常某",":address"=>"宣武区",":phone"=>"18343333333"));
- 使用问号(?)参数,需要传递一个索引数组,数组中每个值的位置都要对应每个问号参数。
<?php
//省略上面的内容
$query = "INSERT INTO userInfo(name, address, phone) VALUES(?, ?, ?)";
$stmt = $dbh->prepare($query); //调用PDO对象中的prepare()方法
//传递一个数组为预处理查询中的命名参数绑定值,并执行一次
$stmt->execute(array("赵某某","海淀区","15333333333"));
//再次传递一个数组为预处理查询中的命名参数绑定值,并执行第二次插入数据
$stmt->execute(array("常某","宣武区","18343333333"));