今天这篇文章,我们来简单的学习一下 PDO 中的预处理语句以及事务的使用,它们都是在 PDO 对象下的操作,而且并不复杂,简单的应用都能很容易地实现。只不过大部分情况下,大家都在使用框架,手写的机会非常少。

预处理语句功能

预处理语句就是准备好一个要执行的语句,然后返回一个 PDOStatement 对象。一般我们会使用 PDOStatement 对象的 execute() 方法来执行这条语句。为什么叫预处理呢?因为它可以让我们多次调用这条语句,并且可以通过占位符来替换语句中的字段条件。相比直接使用 PDO 对象的 query() 或者 exec() 来说,预处理的效率更高,它可以让客户端/服务器缓存查询和元信息。当然,更加重要的一点是,占位符的应用可以有效的防止基本的 SQL 注入攻击,我们不需要手动地给 SQL 语句添加引号,直接让预处理来解决这个问题,相信这一点是大家都学习过的知识,也是我们在面试时最常见到的问题之一。

// 使用 :name 形式创建一个只进游标的 PDOStatement 对象
$stmt = $pdo->prepare("select * from zyblog_test_user where username = :username", [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]); var_dump($stmt);
// object(PDOStatement)#2 (1) {
// ["queryString"]=>
// string(57) "select * from zyblog_test_user where username = :username"
// } $stmt->execute([':username' => 'aaa']);
$aUser = $stmt->fetchAll(); $stmt->execute([':username' => 'bbb']);
$bUser = $stmt->fetchAll(); var_dump($aUser);
// array(1) {
// [0]=>
// array(8) {
// ["id"]=>
// string(1) "1"
// [0]=>
// string(1) "1"
// ["username"]=>
// string(3) "aaa"
// …… var_dump($bUser);
// array(1) {
// [0]=>
// array(8) {
// ["id"]=>
// string(1) "2"
// [0]=>
// string(1) "2"
// ["username"]=>
// string(3) "bbb"
// ……

prepare() 方法的第一个参数就是我们需要执行的 SQL 语句,在这段代码中,我们使用的是 :xxx 形式的占位符,所以在调用 prepare() 方法返回的 PDOStatement 对象的 execute() 方法时,我们需要指定占位符的值。在代码中,我们使用这一条 SQL 语句,通过替换不同的占位符内容,实现了两次查询。

prepare() 方法的第二个参数是为返回的 PDOStatement 对象设置的属性。常见用法是:设置 PDO::ATTR_CURSOR 为 PDO::CURSOR_SCROLL,将得到可滚动的光标。 某些驱动有驱动级的选项,在 prepare 时就设置。PDO::ATTR_CURSOR 是设置数据库游标的类型,而 PDO::CURSOR_FWDONLY 的意思是创建一个只进游标的 PDOStatement 对象。此为默认的游标选项,因为此游标最快且是 PHP 中最常用的数据访问模式。关于数据库游标的知识大家可以自行查阅相关的内容。

此外,PDOStatement 还可以通过 bindParam() 方法来绑定占位符数据,我们将在后面学习 PDOStatement 对象相关的文章中继续学习。

接下来,我们再看一下使用 ? 号占位符来实现查询,? 号占位符在绑定的时候是以下标形式进行绑定的。

// 使用 ? 形式创建一个只进游标的 PDOStatement 对象
$stmt = $pdo->prepare("select * from zyblog_test_user where username = ?", [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]); $stmt->execute(['aaa']);
$aUser = $stmt->fetchAll(); var_dump($aUser);
// array(1) {
// [0]=>
// array(8) {
// ["id"]=>
// string(1) "1"
// [0]=>
// string(1) "1"
// ["username"]=>
// string(3) "aaa"
// ……

当然,这种预编译语句不仅限于查询语句,增、删、改都是可以的,而且也都是支持占位符的。在 PHP中操作数据库的预处理语句 这篇文章中有详细的示例。

事务能力

关于事务想必大家也都有一定的了解,所以在这里也不介绍具体的概念了,我们只看看在 PDO 中事务是如何实现的。首先,我们先看下在没有事务的情况下会发生什么。

$pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)"); // 成功插入

$pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)"); // 报错停止整个PHP脚本执行
// Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog_test.tran_innodb2' doesn't exist

假设这两个表需要同时更新,但第二条语句报错了。在没有事务的情况下,我们第一条数据是会正常插入成功的,这并不是我们需要的结果。在这时,就需要事务能力的帮助,让我们能够让两个表要么同时成功,要么同时失败。

try {
// 开始事务
$pdo->beginTransaction(); $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)");
$pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)"); // 不存在的表 // 提交事务
$pdo->commit();
} catch (Exception $e) {
// 回滚事务
$pdo->rollBack();
// 输出报错信息
echo "Failed: " . $e->getMessage(), PHP_EOL;
// Failed: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog_test.tran_innodb2' doesn't exist
}

首先就是 beginTransaction() 方法,它是用来关闭数据库的自动提交,并启动一个事务,在这个方法之后,只有遇到 commit() 或者 rollBack() 方法后才会关闭这个事务。

commit() 方法就是操作过程中没有出现意外的话,就将在 beginTransaction() 之后的所有数据操作一起打包提交。

rollBack() 是回滚数据,当 beginTransaction() 之后的某一条语句或者代码出现问题时,回滚之前的数据操作,保证 beginTransaction() 之后的所有语句要么都成功,要么都失败。

就是这样三个简单的函数,就为我们完成了整个事务操作。关于事务的深入学习我们会在将来深入地研究 MySQL 时再进行探讨。在这里我们需要注意的是,PDO 对象最好指定错误模式为抛出异常,如果不指定错误模式的话,事务中出现的错误也不会直接报错,而是返回错误码,我们需要通过错误码来确定是否提交或回滚。这样远没有异常机制来的简洁直观。

总结

我们简单的梳理并学习了一下 PDO 中的预处理和事务相关的知识,接下来就要进入 PDOStatement 对象相关内容的学习。PDOStatement 对象就是 PDO 的预处理对象,也就是在日常开发中我们会接触到的最多的数据操作对象。这块可是重点内容,大家可不能松懈了哦!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP%E4%B8%AD%E7%9A%84PDO%E6%93%8D%E4%BD%9C%E5%AD%A6%E4%B9%A0%EF%BC%88%E4%BA%8C%EF%BC%89%E9%A2%84%E5%A4%84%E7%90%86%E8%AF%AD%E5%8F%A5%E5%8F%8A%E4%BA%8B%E5%8A%A1.php

参考文档:

https://www.php.net/manual/zh/pdo.prepare.php

https://www.php.net/manual/zh/pdo.begintransaction.php

https://www.php.net/manual/zh/pdo.commit.php

https://www.php.net/manual/zh/pdo.rollback.php

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

PHP中的PDO操作学习(二)预处理语句及事务的更多相关文章

  1. PHP中的PDO操作学习(三)预处理类及绑定数据

    要说 PDO 中最强大的功能,除了为不同的数据库提供了统一的接口之外,更重要的就是它的预处理能力,也就是 PDOStatement 所提供的功能.因为它的存在,才让我们可以安心地去使用而不用操心 SQ ...

  2. PHP中的PDO操作学习(四)查询结构集

    关于 PDO 的最后一篇文章,我们就以查询结果集的操作为结束.在数据库的操作中,查询往往占的比例非常高.在日常的开发中,大部分的业务都是读多写少型的业务,所以掌握好查询相关的操作是我们学习的重要内容. ...

  3. PHP中使用PDO操作事务的一些小测试

    关于事务的问题,我们就不多解释了,以后在学习 MySQL 的相关内容时再深入的了解.今天我们主要是对 PDO 中操作事务的一些小测试,或许能发现一些比较好玩的内容. 在 MyISAM 上使用事务会怎么 ...

  4. PDO 学习与使用 ( 二 ) PDO 数据提取 和 预处理语句

    以数据库 msg 为例,说明 PDO 的数据提取.预处理语句: mysql> show tables;+---------------+| Tables_in_msg |+----------- ...

  5. PHP中操作数据库的预处理语句

    今天这篇文章的内容其实也是非常基础的内容,不过在现代化的开发中,大家都使用框架,已经很少人会去自己封装或者经常写底层的数据库操作代码了.所以这回我们就来复习一下数据库中相关扩展中的预处理语句内容. 什 ...

  6. iOS中 Swift初级入门学习(二)

    // Copyright (c) 2015年 韩俊强. All rights reserved. // import Foundation /* // 控制语句 // for - in // 遍历字符 ...

  7. Spring框架中的aop操作之二 通过配置文件实现增强

    aop表达式写法 配置文件代码: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&q ...

  8. python中字符串常见操作(二)

    # 可迭代对象有:字典,列表,元组,字符串,集合 str1 = '192.168.1.1' str2 = 'as df gh jk' str3 = '小李子' str4 = ['aa','bb','c ...

  9. MySQL学习(二)——SQL语句创建删除修改以及中文乱码问题

    一.对数据库的操作 1.创建一个库 create database 库名; 创建带有编码的:create database 库名 character set 编码; 查看编码:show create ...

随机推荐

  1. Git-02-版本回退

    环境准备 1 修改readme.txt内容 Git is a distributed version control system. Git is free software. 2 git statu ...

  2. MySQL-07-information_schema/show

    information_schema.tables视图 DESC information_schema.TABLES /** TABLE_SCHEMA ---->库名 TABLE_NAME -- ...

  3. STM32—驱动GY85-IMU模块

    GY85是一个惯性测量模块,内部集成了三轴加速度计.三轴陀螺仪.电子罗盘.气压传感器等芯片,用于测量和报告设备速度.方向.重力,模块可以将加速度计.陀螺仪.电子罗盘等传感器的数据进行综合,在上位机可以 ...

  4. Linux搭建Ldap服务器

    一,服务器安装 yum install -y openldap openldap-clients openldap-servers migrationtools 二,配置ldap服务器 2.1配置ld ...

  5. NOIP 模拟 $27\; \rm 牛半仙的妹子图$

    题解 \(by\;zj\varphi\) 颜色数很少,考虑枚举颜色数. 建出来一棵最小生成树,可以证明在最小生成树上,一个点到另一个点的路径上的最大权值最小(易证,考虑 \(\rm kruskal\) ...

  6. Vamware没有卸载干净,导致无法重装,无法删除VMware旧版本,请与技术小组联系

    原因:注册表没有清理干净!!! 问题:把文件夹清理了n遍,却无法重装VMware,报错如标题. 原因:相关注册表没删完. 解决办法: - 1.创建一个.txt文本: - 2.将下面的内容复制到.txt ...

  7. c#反射入门篇(Reflection)——MethodInfo 发现方法的属性

    网站:https://www.jianshu.com/p/52dc85668d00 也算记录自己的学习篇=.= 适合入门看 这里简单介绍下MethodInfo和他基本的几个方法 简介 MethodIn ...

  8. 【mysql】关联查询_子查询_排序分组优化

    1. 关联查询优化 1.1 left join 结论: ①在优化关联查询时,只有在被驱动表上建立索引才有效! ②left join 时,左侧的为驱动表,右侧为被驱动表! 1.2 inner join ...

  9. 【转】互联网项目中mysql应该选什么事务隔离级别

    作者:孤独烟 转自:https://www.cnblogs.com/rjzheng/p/10510174.html 摘要 企业千万家,靠谱没几家.社招选错家,亲人两行泪. 祝大家金三银四跳槽顺利! 引 ...

  10. linux(1)------vmvear虚拟机安装linux

    1.VMvare14(个人下载,软件付费,自行解决) 2.CentOS下载           https://www.centos.org/download/    官方网址,后期会跳转本地镜像站 ...