PDO概述
1.PDO是一种数据库访问抽象层,你不必使用以前的 mysqli_xx 之类只能访问 mysql数据库。使用PDO可以连接mysql、msssql、oracle等等,而不必重写代码。
2.PDO也是现在PHP推荐和默认的数据库连接引擎,更为先进。
3.PDO默认情况下需要在PHP5.1以上的版本运行。
连接MySQL
1.使用PDO类来连接MySQL数据库。在PDO的构造参数里,传递数据库信息
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); } catch (PDOException $e) { //输出错误信息 echo $e->getMessage(); }
增删改查
1.使用exec()方法增删改一条记录,返回影响行数。
(1)删除:
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //删除 echo $pdo->exec("DELETE FROM one WHERE id='1'"); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
返回1代表删除成功
(2)修改:
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //修改 $pdo->exec("UPDATE one SET user='xixi' WHERE id='1'"); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
2.使用query()方法设置字符集。
设置字符集后修改
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //修改 $pdo->exec("UPDATE one SET user='王西西' WHERE id='1'"); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
(3)新增:
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //新增 $pdo->exec("INSERT INTO one (user, math, english, chinese, create_time) VALUES ('西西', 88, 88, 88, NOW())"); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
3.使用 query()方法获取准备对象
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = "SELECT * FROM one"; //得到准备对象 $stmt = $pdo->query($sql, PDO::FETCH_NUM); //输出准备对象 var_dump($stmt); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
准备对象结果:
object(PDOStatement)[2]
public 'queryString' => string 'SELECT * FROM one' (length=17)
4.使用fetch()方法可以得到当前指针的记录。
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = "SELECT * FROM one"; //获取当前指针记录,并将指针下移一行 $stmt = $pdo->query($sql, PDO::FETCH_NUM); //输出指针记录 var_dump($stmt->fetch()); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
第一行指针记录结果:
array (size=6)
0 => string '1' (length=1)
1 => string '王西西' (length=9)
2 => string '90' (length=2)
3 => string '90' (length=2)
4 => string '90' (length=2)
5 => string '2018-02-28 14:27:03' (length=19)
5.使用while循环遍历记录。
6. 使用PDO::FETCH_ASSOC参数,可以选择格式化结果,相对应的还有PDO::FETCH_NUM,默认为:PDO::FETCH_BOTH。
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = "SELECT * FROM one"; //得到准备对象 $stmt = $pdo->query($sql, PDO::FETCH_NUM); while ($row = $stmt->fetch()) { print_r($row); } } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
FETCH_NUM以索引数组来显示源代码查看
Array
(
[0] => 1
[1] => 王西西
[2] => 90
[3] => 90
[4] => 90
[5] => 2018-02-28 14:27:03
)
Array
(
[0] => 2
[1] => 西西
[2] => 88
[3] => 88
[4] => 88
[5] => 2018-02-28 14:33:17
)
7.使用fetchAll()一次性输出所有记录。
//一次性输出所有数据,如果量大的话,压力大,不推荐
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = "SELECT * FROM one"; //得到准备对象 $stmt = $pdo->query($sql); print_r($stmt->fetchAll()); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
输出结果:
Array
(
[0] => 1
[1] => 王西西
[2] => 90
[3] => 90
[4] => 90
[5] => 2018-02-28 14:27:03
)
Array
(
[0] => 2
[1] => 西西
[2] => 88
[3] => 88
[4] => 88
[5] => 2018-02-28 14:33:17
)
8.使用fetchObject()方法用对象模式输出。
//对象形式输出记录
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = "SELECT * FROM one"; //得到准备对象 $stmt = $pdo->query($sql); while ($object = $stmt->fetchObject()) { echo $object->user; echo '<br>'; } } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
打印每一个的user
王西西
西西
预处理语句
1.每次查询发送给 MySQL 服务器时,都必须解析该查询的语法,确保结构正确并能够执行。这是这个过程中必要的步骤,但也确实带来了一些开销。做一次是必要的,但如果反复地执行相同的查询,批量插入多行时就会加大了服务器的负担。准备语句会在服务器上缓存查询的语法和执行过程,而只在服务器和客户端之间传输有变化的列值,以此消除这些额外的开销。
2.PDO 为支持此特性的数据库提供了准备语句功能。因为 MySQL 支持这个特性,所有可以在适当时候使用准备语句。准备语句是使用两个方法实现的:prepare()负责准备要执行的查询,execute()使用一组给定的列参数返回地执行查询。
3.如果采用 prepare 和 execute 方法,还可以防止 SQL 注入等攻击。因为所有的变量都会被自动转义。
4.新增方式,删除和修改均用这模式。
新增方式:
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //新增SQL语句 $sql = "INSERT INTO one (user, math, chinese, english, create_time) VALUES ('测试', 88, 88, 88, NOW())"; //获取准备对象把这个语句放进去 $stmt = $pdo->prepare($sql); //执行 $stmt->execute(); } catch (PDOException $e) { //错误信息 echo $e->getMessage();
5.使用 lastInsertId()方法可以得到最新新增的ID。
//获取最后新增的 ID
echo $pdo->lastInsertId();
6.使用 rowCount()方法获取增删改的影响行数
//增删改的影响行数
echo $stmt->rowCount();
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //新增SQL语句 $sql = "INSERT INTO one (user, math, chinese, english, create_time) VALUES ('测试1', 88, 88, 88, NOW())"; //获取准备对象把这个语句放进去 $stmt = $pdo->prepare($sql); //执行 $stmt->execute(); //得到最新ID echo $pdo->lastInsertId(); //影响行数 echo $stmt->rowCount(); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
返回值:
最新ID:4
影响行数:1
7.也可以使用fetchAll、fetch或fetchObject等方法遍历数据。
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = "SELECT * FROM one"; //获取准备对象 $stmt = $pdo->prepare($sql); //必须执行SQL $stmt->execute(); //遍历 while ($obj = $stmt->fetchObject()) { var_dump($obj); } } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
查询结果:
object(stdClass)[3]
public 'id' => string '1' (length=1)
public 'user' => string '王西西' (length=9)
public 'math' => string '90' (length=2)
public 'chinese' => string '90' (length=2)
public 'english' => string '90' (length=2)
public 'create_time' => string '2018-02-28 14:27:03' (length=19)
object(stdClass)[4]
public 'id' => string '2' (length=1)
public 'user' => string '西西' (length=6)
public 'math' => string '88' (length=2)
public 'chinese' => string '88' (length=2)
public 'english' => string '88' (length=2)
public 'create_time' => string '2018-02-28 14:33:17' (length=19)
8.重复执行一个 SQL 查询,通过每次迭代使用不同的参数,这种情况使用预处理语句运行效率最高。使用预处理语句,首先需要在数据库服务器中先准备好“一个 SQL 语句”,但并不需要马上执行。PDO 支持使用“占位符”语法,将变量绑定到这个预处理的 SQL 语句中。另外,PDO 几乎为所支持的所有数据库提供了命令占位符模拟,甚至可以为生来就不支持该概念的数据库模拟预处理语句和绑定参数。这是 PHP 向前迈进的积极一步,因为这样可以使开发人员能够用 PHP 编写“企业级”的数据库应用程序,而不必特别关注数据库平台的能力。
9.对于一个准备好的 SQL 语句,如果在每次执行时都要改变一些列值,这种情况必须使用“占位符”而不是具体的列值,或者只要有需要使用变量作为值的地方,就先使用占位符替代,准备好一个没有传值的 SQL 语句,在数据库服务器的缓存区等待处理,然后再去单独赋给占位符具体的值,再通过这个准备好的预处理语句执行。在 PDO 中有两种使用占位符的语法:“命令参数”和“问号参数”,使用哪一种语法看个人的喜好。
10.使用?号语法新增多条记录。
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = "INSERT INTO one (user, math, chinese, english, create_time) VALUES (?, ?, ?, ?, NOW())"; //获取准备对象 $stmt = $pdo->prepare($sql); //执行 $stmt->execute(array('西西1', 77, 77, 77)); $stmt->execute(array('西西2', 88, 88, 88)); $stmt->execute(array('西西3', 99, 99, 99)); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
11.使用:名称语法新增多条记录
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = "INSERT INTO one (user, math, chinese, english, create_time) VALUES (:user, :math, :chinese, :english, NOW())"; //获取准备对象 $stmt = $pdo->prepare($sql); //执行 $stmt->execute(array(':user'=>'西西4', ':math'=>77, ':chinese'=>77, ':english'=>77)); $stmt->execute(array(':user'=>'西西5', ':math'=>88, ':chinese'=>88, ':english'=>88)); $stmt->execute(array(':user'=>'西西6', ':math'=>99, ':chinese'=>99, ':english'=>99)); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
预处理扩展
1.使用:名称实现变量查询。
查询方式一:
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = 'SELECT * FROM one WHERE id=:id'; //获得准备对象 $stmt = $pdo->prepare($sql); //执行查询(查询数组查询第一条) $stmt->execute(array(':id'=>1)); //输出 var_dump($stmt->fetchObject()); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
查询ID=1结果
object(stdClass)[3]
public 'id' => string '1' (length=1)
public 'user' => string '王西西' (length=9)
public 'math' => string '90' (length=2)
public 'chinese' => string '90' (length=2)
public 'english' => string '90' (length=2)
public 'create_time' => string '2018-02-28 14:27:03' (length=19)
查询方式二:
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = 'SELECT * FROM one WHERE id=?'; //获得准备对象 $stmt = $pdo->prepare($sql); //执行查询 $stmt->execute(array(1)); //输出 var_dump($stmt->fetchObject()); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
查询ID=1结果
object(stdClass)[3]
public 'id' => string '1' (length=1)
public 'user' => string '王西西' (length=9)
public 'math' => string '90' (length=2)
public 'chinese' => string '90' (length=2)
public 'english' => string '90' (length=2)
public 'create_time' => string '2018-02-28 14:27:03' (length=19)
2.使用bindValue()方法绑定查询参数。
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //SQL语句 $sql = 'SELECT * FROM one WHERE id=:id'; //获得准备对象 $stmt = $pdo->prepare($sql); //参数绑定 $stmt->bindValue(':id', 1); //执行查询 $stmt->execute(); //输出 var_dump($stmt->fetchObject()); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); }
查询ID=1结果
object(stdClass)[3]
public 'id' => string '1' (length=1)
public 'user' => string '王西西' (length=9)
public 'math' => string '90' (length=2)
public 'chinese' => string '90' (length=2)
public 'english' => string '90' (length=2)
public 'create_time' => string '2018-02-28 14:27:03' (length=19)
3.bindParam()方法和bindValue()一样,唯一的区别就是bindParam只能传递变量,而bindValue均可。
事务处理
1.所谓事务,说白了,就是一组SQL关联的操作,如果其中一条SQL有误没有执行,而其他的SQL都会撤销执行。
2.PDO为能够执行事务的数据库提供了事务支持。有3个PDO 方法可以完成事务任务:beginTransaction()、commit()和 rollback()。
3.MySQL 数据库类型为 InnoDB 方可启用事务处理。
<?php try { //PDO连接 $pdo = new PDO('mysql:host=127.0.0.1;dbname=xixi', 'xixi', '123456'); //设置字符集 $pdo->query("SET NAMES UTF8"); //设置错误异常处理方式 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //开启事务 $pdo->beginTransaction(); $pdo->exec('UPDATE one SET math=math+30 WHERE id=1'); $pdo->exec('UPDATE one SET math=math-30 WHERE id=2'); //提交,都正确了 $pdo->commit(); } catch (PDOException $e) { //错误信息 echo $e->getMessage(); //回滚,撤销所有SQL执行 $pdo->rollBack(); }
错误信息:
SQLSTATE[22003]: Numeric value out of range: 1690 BIGINT UNSIGNED value is out of range in '(`xixi`.`one`.`math` - 30)'