执行 sql 语句:exec()、query()、perpare();
1、query 用来处理有结果集的,如 select,返回 PDOStatement 对象,失败返回 false(当为 PDO::ERRMODE_SILENT,这也是默认的值)
2、exec 用来处理有返回影响行数的(int),如 insert(插入的行数)、delete(删除的行数)、update(和原数值不等才算),失败返回 false(当为 PDO::ERRMODE_SILENT,这也是默认的值)3、prepare 执行所有 sql,可以完全替代 query,exec 的功能
错误报告是针对执行的 sql 出错时
PDO::ERRMODE_SILENT(0):默认 不提示任何错误,连接时无论如何都会提示,只有在执行后面的方法时才会起作用
PDO::ERRMODE_WARNING(1):警告
PDO::ERRMODE_EXCEPTION(2):异常(推荐使用)用 try catch 捕获,也可以手动抛出异常 new PDOException($message, $code, $previous)
一 PDO 基本认识
什么事 PDO
POD(PHP Data Object)扩展在 PHP5 中加入,PHP6 中将默认识用 PDO 连接 数据库 ,所有非 PDO 扩展将会在 PHP6 被从扩展中移除。该扩展提供 PHP 内置类 PDO 来对数据库进行访问,不同数据库使用相同的 方法 名,解决数据库连接不统一的问题。
如何开启 PDO 扩展
① 找到 php 目录下的 php.ini 配置文件
② 开启 pdo_mysql.dll 扩展(按需加载)
; 开启 php_pdo_mysql 数据对象扩展
extension=php_pdo_mysql.dll
③ 重启 Apache 软件
④使用 phpinfo 函数判断 pdo_mysql 是否开启成功
二、PDO::__construct 创建一个表示数据库连接的 PDO(实例的对象)
PDO::__construct() ( string $dsn [, string $username [, string $password]] )
$dsn:数据源,字符串类型,格式:mysql:host=localhost;dbname=project
$username:用户名,连接数据库的用户名
$password:密码,连接数据库的密码
<?php
/* 如果试图连接到请求的数据库失败,则 PDO::__construct() 抛出一个 PDO 异常(PDOException)*/
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser'; // 数据库用户名
$password = 'dbpass'; // 数据库密码
try { $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {echo 'Connection failed:' . $e->getMessage();
}
?>
三、PDO::exec 执行一条 SQL 语句,并返回受影响的行数(数据的增删改)
int PDO::exec (string $statement)
PDO::exec() 在一个单独的函数调用中执行一条 SQL 语句,返回受此语句影响的行数。
PDO::exec() 不会从一条 SELECT 语句中返回结果。对于在程序中只需要发出一次的 SELECT 语句,可以考虑使用 PDO::query()。对于需要发出多次的语句,可用 PDO::prepare() 来准备一个 PDOStatement 对象并用 PDOStatement::execute() 发出语句。
此函数可能返回布尔值 FALSE,但也可能返回等同于 FALSE 的非布尔值(没有受影响的行,则 PDO::exec() 返回 0,判断是布尔值 false 还是 0 时可以用 !== 或者 === 进行全比较)。
<?php
$dbh = new PDO('odbc:sample', 'db2inst1', 'ibmdb2');
/* 删除 FRUIT 数据表中满足条件的所有行 */
$count = $dbh->exec("DELETE FROM fruit WHERE colour ='red'");
/* 返回被删除的行数 */
print("Deleted $count rows.\n");
?>
以上例程会输出:
Deleted 1 rows.
四、PDO::query 执行一条 SQL 语句,返回一个结果集作为 PDOStatement 对象
<?php
header("content-type:text/html;charset=utf-8");
$params = array (
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
);
$pdo = new PDO('mysql:host=127.0.0.1;dbname=bbs;port=3306', 'root', 'root',$params);
$statement = "select * from user";
$stmt = $pdo->query($statement);
echo "<pre>";
var_dump($stmt);
/*
以下是输出的结果, 可以看出返回一个结果集作为 PDOStatement 对象
object(PDOStatement)#2 (1) {["queryString"]=>
string(18) "select * from user"
}
*/
?>
注意:
1、query 和 exec 都可以执行所有的 sql 语句,只是返回值不同而已。
2、query 可以实现所有 exec 的功能。
3、当把 select 语句应用到 exec 时,总是返回 0
五、PDO 中的遍历操作
要使用到的知识点:
- mixed PDOStatement::fetch (int $fetch_style):实现对数据的遍历输出,每次只能遍历一条记录,然后指针向下移动一位!
参数说明:
PDO::FETCH_ASSOC:把一条记录遍历到关联数组中
PDO::FETCH_NUM:把一条记录遍历到索引型数组中
PDO::FETCH_BOTH:把一条记录遍历到混合型数组中
PDO::FETCH_OBJ:把一条记录遍历到对象中
PDO::FETCH_BOUND (bindColumn):把某个变量绑定到结果集中的某个列
示例代码:PDO::FETCH_ASSOC
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、组装 SQL 语句
$sql = "select * from tb_admin";
//4、执行 SQL 语句
$stmt = $pdo->query($sql);
//5、获取总记录数
$count = $stmt->rowCount();
//6、遍历数据到关联数组中
for($i=0;$i<$count;$i++) {
// 把一条记录遍历到关联型数组中
$row = $stmt->fetch(PDO::FETCH_ASSOC);
var_dump($row);
}
?>
示例代码:PDO::FETCH_BOUND(bindColumn)
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、组装 SQL 语句
$sql = "select * from tb_admin";
//4、执行 SQL 语句
$stmt = $pdo->query($sql);
$count = $stmt->rowCount();
//5、使用 bindColumn 实现列绑定
$stmt->bindColumn(1,$id); // 把变量 $id 绑定到结果集中的第 1 列
$stmt->bindColumn(2,$username); // 把变量 $username 绑定到结果集中的第 2 列
$stmt->bindColumn(3,$password); // 把变量 $password 绑定到结果集中的第 3 列
//6、使用 for 循环实现对结果集的遍历
for($i=0;$i<$count;$i++) {
// 指定 fetch 的绑定方式为 PDO::FETCH_BOUND, 否则 bindColumn 不会生效
$stmt->fetch(PDO::FETCH_BOUND);
// 输出 $id/$username 以及 $password 的基本信息
echo $id;
echo '-';
echo $username;
echo '-';
echo $password;
echo '<hr />';
}
?>
要用到的知识点:
- array PDOStatement::fetchAll()
主要功能:把数据表中的记录返回到一个二维数组中
示例代码:
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、组装 SQL 语句
$sql = "select * from tb_admin";
//4、执行 SQL 语句
$stmt = $pdo->query($sql);
//5、把数据表中的所有记录返回到一个二维数组中
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
//6、遍历结果集
foreach($data as $row) {echo $row['id'];
echo '-';
echo $row['username'];
echo '-';
echo $row['password'];
echo '<hr />';
}
?>
要用到的知识点:
- string PDOStatement::fetchColumn ([int $column_number = 0] )
主要功能:遍历结果集当前行的某一列信息
参数说明:
$column_number:第几列,从 0 开始
示例代码:
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、组装 SQL 语句
$sql = "select * from tb_admin";
//4、执行 SQL 语句
$stmt = $pdo->query($sql);
//5、获取总记录数
$count = $stmt->rowCount();
//6、使用 for 循环遍历结果集
for($i=0;$i<$count;$i++) {$id = $stmt->fetchColumn(0);
echo $id.'<hr />';
}
?>
六、PDO 扩展中的预处理功能
- PDO::prepare (string $statement):定义预处理语句 返回值为 PDOStatement 对象或者为 false
- PDOStatement::execute ([array $input_parameters] ):执行预处理语句 返回值为布尔值
- PDOStatement::bindParam (mixed $parameter , mixed &$variable) 实现参数绑定
返回值为布尔值
$parameter:要绑定的参数 $variable:要设置的参数值,按引用传递
特别注意:如果以上参数,使用的是?问号标识,其绑 定时索引是从 1 开始的!
预处理功能就是在 SQL 语句结构与形式相同的情况下,只有参数不同所采用的一种数据处理机制,其极大的减少了带宽的浪费。
示例①使用文本标识
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、组装 SQL 语句
$sql = "insert into tb_admin values (null,:username,:password,:time)";
//4、定义预处理语句
$stmt = $pdo->prepare($sql);
//5、使用 execute 实现参数的传递
$password = md5('123456');
$time = time();
$data = array(':username'=>'zhangsan',
':password'=>$password,
':time'=>$time
);
$stmt->execute($data);
?>
示例②使用问号标识
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、组装 SQL 语句
$sql = "insert into tb_admin values (null,?,?,?)";
//4、定义预处理语句
$stmt = $pdo->prepare($sql);
//5、使用 execute 传递参数
$password = md5('123456');
$time = time();
$data = array(0=>'lisi',
1=>$password,
2=>$time
);
$stmt->execute($data);
?>
示例③使用文本标识时参数绑定
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、组装 SQL 语句
$sql = "insert into tb_admin values (null,:username,:password,:time)";
//4、定义预处理语句
$stmt = $pdo->prepare($sql);
//5、绑定参数
$stmt->bindParam(':username',$username);
$stmt->bindParam(':password',$password);
$stmt->bindParam(':time',$time);
//6、设置参数
$username = 'wangwu';
$password = md5('123456');
$time = time();
//7、执行预处理语句
$stmt->execute();
?>
示例④使用? 标识参数绑定时
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、组装 SQL 语句
$sql = "insert into tb_admin values (null,?,?,?)";
//4、定义预处理语句
$stmt = $pdo->prepare($sql);
//5、使用 bindParam 实现参数绑定
$stmt->bindParam(1,$username);
$stmt->bindParam(2,$password);
$stmt->bindParam(3,$time);
//6、设置参数
$username = 'zhaoliu';
$password = md5('123456');
$time = time();
//7、执行预处理语句
$stmt->execute();
$username = 'tianqi';
$password = md5('123456');
$time = time();
$stmt->execute();
?>
七、PDO 中事务处理
事务处理主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
在事务处理中,所有步骤(操作)要么都成功,要么都失败。如果所有步骤都成功,则认为事务处理成功。如果有一个步骤出现了问题,则认为事务处理失败。
① 开启事务 bool PDO::beginTransaction (void)
② 提交事务 bool PDO::commit (void)
③ 回滚事务 bool PDO::rollBack (void)
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
$pdo = new PDO($dsn, $user, $pass);
//3、开启事务处理
$pdo->beginTransaction();
//4、定义交易流程(两个步骤:扣钱与加钱)$flag = true;
$sql = "update tb_bank set money = 2000 where id = 1";
$affected_rows = $pdo->exec($sql);
if(!$affected_rows) {$flag = false;}
$sql = "update tb_bank set money = 0.1 where id = 3";
$affected_rows = $pdo->exec($sql);
if(!$affected_rows) {$flag = false;}
//5、判断交易是否成功
if($flag) {
// 交易成功,提交事务
$pdo->commit();
} else {
// 交易失败,回滚事务
$pdo->rollback();
}
?>
八、PDO 中的异常类
PHP 5 提供了一种新的面向对象的错误处理方法。
异常处理用于在指定的错误(异常)情况发生时改变脚本的正常流程。这种情况称为异常。
PDO 中的异常捕获基本语法:
try {
存在潜在错误的代码;
if(逻辑错误) {
// 手工输出异常
throw new PDOException(‘错误的文本信息’,’错误号’);
}
} catch(PDOException $e) {echo‘错误号:’.$e->getCode();
echo‘错误行号:’.$e->getLine();
echo‘错误的文本信息:’.$e->getMessage();}
示例代码
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、定义相关参数
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dsn = "$dbms:host=localhost;dbname=project";
//3、实例化 pdo 类
try {
$pdo = new PDO($dsn,$user,$pass);
//4、定义 SQL 语句
$time = time();
$sql = "insert into tb_admin values (null,abcd,'123456',$time)";
$flag = $pdo->exec($sql);
//5、手工抛出异常
if($flag === false) {throw new PDOException('SQL 语句错误',1000);
}
} catch(PDOException $e) {
echo '错误号:'.$e->getCode().'<hr />';
echo '错误行:'.$e->getLine().'<hr />';
echo '错误信息:'.$e->getMessage();
}
?>
九、PDO 中属性的获取与设置
1、属性的获取与设置
要用到的知识点:
设置:set 获取:get 属性:attribute
bool PDO::setAttribute (int $attribute , mixed $value):设置属性
mixed PDO::getAttribute (int $attribute):获取属性
参数说明:
$attribute:要设置或获取的属性
$value:要设置的属性值
2、PDO 中常用的属性
① PDO::ATTR_AUTOCOMMIT:自动提交,常用于事务处理(语句事务)
参数值:
1:自动提交
0:关闭自动提交
② PDO::ATTR_CASE:结果集大小写
参数值:
PDO::CASE_LOWER(2):把结果集(字段名称)全部转化为小写
PDO::CASE_UPPER(1):把结果集(字段名称)全部转化为大写
PDO::CASE_NATURAL(0):正常返回
③ PDO::ATTR_PERSISTENT:长连接
名词解析:
短连接:连接 à 发送 SQL 语句 à 执行 SQL 语句 à 关闭
长连接:连接 à a 发送 SQL 语句 à 执行 SQL 语句 à a 发送 SQL 语句 à 执行 SQL 语句 …
示例代码
<?php
//1、设置响应头信息
header('Content-type:text/html; charset=utf-8');
//2、实例化 pdo 类
$dbms = 'mysql';
$user = 'root';
$pass = 'mysql';
$dbname = 'project';
$dsn = "$dbms:host=localhost; dbname=$dbname";
// 设置长连接
$data = array(PDO::ATTR_PERSISTENT=>true);
$pdo = new PDO($dsn, $user, $pass, $data);
//3、设置常用属性
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0); // 关闭自动提交
$pdo->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER); // 结果集字段全部转化为小写
//4、获取常用属性值
echo '自动提交:';
var_dump($pdo->getAttribute(PDO::ATTR_AUTOCOMMIT));
echo '<hr />';
echo '结果集大小写:';
var_dump($pdo->getAttribute(PDO::ATTR_CASE));
echo '<hr />';
echo '长连接:';
var_dump($pdo->getAttribute(PDO::ATTR_PERSISTENT));
echo '<hr />';
?>
十、总结
① PDO 扩展技术
PDO 的基本概念以及为什么需要 PDO
② PDO 类(增删改查)
增删改:$pdo->exec($sql) 返回受影响的行数
查询:$pdo->query($sql) 返回 PDOStatement 类,fetch 方法、fetchAll 方法、fetchColumn 方法
③ PDO 中的预处理
减少 SQL 语句的传递,只传递相关的参数,这样可以减少带宽的浪费
prepare stmt1 from‘insert into tb_admin values (null,?,?,?)’;
设置参数
set @参数 = 参数的值;
执行预处理
execute stmt1 using @参数;
④ PDO 中的事务处理
开启事务 beginTransaction()
提交事务 commit()
回滚事务 rollback()
⑤ 异常类 PDOException
try {
// 存在潜在错误的语句
if(逻辑错误) {
// 手工抛出异常
throw new PDOException(‘错误信息’,’错误号’);
}
} catch(PDOException $e) {
echo $e->getCode();
echo $e->getLine();
echo $e->getMessage();
}
⑥ 属性的设置与获取
setAttribute
getAttribute