PHP PDO和MySQLi

39
我刚刚完成了PHP的入门课程,在stackoverflow论坛上,人们推荐我转向PDO、预处理语句或MYSQLi,我简要地查阅了手册,但大部分内容都超出了我的理解范围。 我一直在使用mysql_*函数,所以这些概念对我来说是新的。我认为它们用于访问和执行特定于数据库的操作,但我不确定。那么PDO、预处理语句和MySQLi之间有什么区别,它们是实现相同任务的不同功能吗?它们在脚本中是否兼容,还是“选择其中一种”?最后哪种提供最佳性能?更新:谢谢你们的回答,我将继续寻找更多关于PDO的教程。对于参考,我也发现以下帖子有用:Which one is fast and light - mysqli or PDO mysqli or PDO - what are the pros and cons?

3
我建议从这里开始阅读:http://www.phpro.org/tutorials/Introduction-to-PHP-PDO.html。 - Brad
感谢您的所有答案并为我澄清。 - grasshopper
这里有一个关于PDO的不错教程:http://a2znotes.blogspot.in/2014/09/introduction-to-pdo.html - RN Kushwaha
6个回答

41
在基本层面上,mysql、mysqli和PDO扩展都回答了“我如何与数据库通信?”这个问题。它们都提供了连接到数据库并发送和检索数据的功能和函数。您可以同时使用它们来建立多个与数据库的连接,但通常这是无意义的。
mysql*是一个非常简单的扩展,基本上只允许您连接到数据库,向其发送SQL查询,没有其他太多的功能。
mysqli通过添加参数化查询和一些其他功能来改进它(正如其名称所示)。
PDO是一个将几个数据库驱动程序抽象成一个包的扩展,即它允许您使用相同的代码连接到MySQL、Oracle、MS SQL Server和许多其他数据库,而不需要使用特定于数据库的扩展或在切换数据库时重写代码(至少在理论上)。它还支持参数化查询。
如果您知道自己将仅使用MySQL,则mysqli是一个不错的选择。特别是因为您可以以过程化方式使用它,这是您已经从mysql扩展中习惯的方式。如果您不熟悉OOP,那很有帮助。否则,PDO是一个不错的面向对象、灵活的数据库连接器。

* 注意,mysql扩展现在已经弃用,并且将来会被移除。这是因为它古老、充满不良实践并且缺乏一些现代特性。不要使用它来编写新代码。


1
终于有人能够用简单直接的方式回答这个问题。谢谢! - Kebman
1
不推荐使用mysqli。 - Your Common Sense
3
@YourCommonSense,我认为你已经失去了常识,特别是因为你在你无处不在的库中使用mysqli。 - deceze
3
@YourCommonSense - 请问在什么情况下需要调用call_user_func()?为什么不直接使用$stmt->bind_param(),这与PDO的$sth->bindParam()并没有太大区别?肯定不是到处投反对票的理由。 - martinstoeckli
2
不行,如果你的值在数组中,你不能在没有引用每个变量的情况下使用bind_param。因此,您不能在bind_params中使用循环。例如,请参见https://dev59.com/pWQo5IYBdhLWcg3wV-Qx。如果没有get_result()可用,那么您将无法获得相同的乐趣来获取您的值。当然这仍然是可行的。但我宁愿称其为“痛苦”而不是“可用性”。 - Your Common Sense
显示剩余4条评论

16

PDO 是 "PHP 数据对象"。我主要使用PDO,所以只能就它的优点发表看法:

  • 适用于比MySQL更多的数据库(可能对您不重要)
  • 编译为C,因此速度更快(据说)
  • 准备好的语句(其他一些也有这个功能)
  • SO似乎很喜欢这个,因此您至少可以在这里获得很多帮助
  • 您可以设置和动态更改各种获取/错误处理模式

你问道:

那么 PDO、准备好的语句和 MySQLi 之间有什么区别...

PDOMySQLi 是DB包装器。 "准备好的语句"是一个完全不同的概念。您可以准备一条可执行多次的查询语句,并且正确参数化的语句是SQL注入安全的(虽然可能不是绝对安全)。这也是您应该使用PDO(或MySQLi)的主要原因,但准备好的语句还可以提高查询的清晰度。

/* mysql_* version */
mysql_connect("host");
$query = "SELECT column FROM db1.t1 WHERE id = ";
foreach ($_GET['id'] as $id) {
   $id = mysql_real_escape_string($id);
   $result = mysql_query($query . "'$id'";
   while ($row = mysql_fetch_assoc($result)) {
      echo "$row[column]\n";
   }
}
//NOTE: it would probably be better to store the resource returned by
//mysql_connect and use that consistently (in query/escape)

/* PDO version */
$pdo = new PDO('mysql:host=HOST', 'user', 'pass');
$query = $pdo->prepare("SELECT column FROM db1.t1 WHERE id = ?";
foreach ($_GET['id'] as $id) {
   $query->execute($id);
   echo $query->fetch(PDO::FETCH_COLUMN);
}
//Notice that you skip the escape step.

你可以使用MySQLi实现基本相同的功能,但我更喜欢PDO的语法。它可能更快,但我也有可能是在胡说八道。还有PEAR MDB2这个很少被提到,当然还有其它的选择。由于PDO已经内置了,我会选择使用它。


2
这个来源指出MySQL和MySQLi速度稍微更快一些:http://code.tutsplus.com/tutorials/pdo-vs-mysqli-which-should-you-use--net-24059 - Daan
你在pdo准备查询语句中漏掉了一个闭合括号“)”。 - mendez7

4
如果您习惯使用mysql_xxx函数,那么我建议您开始转向MySQLi扩展。您也可以选择使用PDO,但如果您只需要支持一个数据库,那么这样做并没有太大的价值。对于您的目的,我建议您切换到MySQLi,因为这样更容易,并且您不会立即获得PDO的好处。可用于MySQLi的函数与您熟悉的mysql_xx函数基本相似。通常可以将现有代码直接替换,然后代码应该继续正常工作。所以这是一个好的起点--让您的代码使用mysqli_xxx而不是mysql_xxx。如果可能的话,我建议您使用面向对象的语法而不是过程式语法。MySQLi支持两种语法,过程式语法更接近您所熟悉的语法,但面向对象的语法在长期运行中更加灵活,一旦您习惯了它,就不会有太大的区别。一旦您将代码转换为使用MySQLi库,并且您熟悉了基础知识,您就可以开始使用更高级的功能,比如预处理语句。但首先要让自己熟悉基础知识。

1

从我的角度来看,我认为差异并不真正明显(取决于你使用它的目的)。看起来PDO只是一个数据库API,将所有其他数据库API合并成一个。因此,如果您需要连接到MS Sql服务器和MySQL服务器,只需调用PDO API并指定特定数据库的驱动程序即可。我猜测,MySQL中的任何未来功能和能力都只能在PDO中使用。因此,基本上只需使用PDO以确保您可以访问所有最新功能。


1

PDO的一个重要优势是平台无关性。这意味着您可以在不必重新编写所有函数调用的情况下迁移到不同的DBMS。这通常是Java(通过JDBC)、.Net(ADO)和大多数其他环境中的做法。优点不仅在于您可以切换DBMS,而且还在于您只需要学习一个API。

至于您的问题,PDO层提供了执行预处理语句的功能。预处理语句的思想是为SQL语句的某些部分创建占位符,这些部分直到运行时才能确定。许多学习者最初通过创建字符串形式的SQL来执行mysqli::query($someQuery)。这有很多问题,其中最突出的是易受SQL注入攻击(请参见stackoverflow.com/questions/5315351以获取类似问题和答案)。使用PDO,您可以避免SQL注入以及处理引号、反斜杠等字符所带来的所有问题。最终结果是您的代码更加安全、可读和可预测。

如果您已经知道如何使用mysqli,那么使用PDO并没有太大区别。上面链接的问题和答案展示了使用PDO预处理语句提交查询的示例,应该是一个有用的指南。


-2
那么PDO、预处理语句和MySQLi之间有什么区别,它们是实现相同任务的不同功能吗?
区别非常简单。PDO可以与预处理语句一起使用,而mysqli则不能。
只需使用本机预处理语句运行一些常规查询,您就可以清楚地看到两个API之间的差异。

这并不是真的,mysqli确实有预处理语句,例如 $stmt = $db->prepare($query);。 - Thomas Williams
@ThomasWilliams 你需要更加注意你所阅读的内容。"usable" 这个词是关键。https://phpdelusions.net/pdo/mysqli_comparison - Your Common Sense
经过一些调查,我相当喜欢pdo的工作方式,但mysqli准备语句也是可用的,我已经使用它们几年了。是的,如果你漏掉了一个逗号并且花费了一段时间来追踪错误,那么这确实很痛苦,但是它确实非常可用。对我来说,唯一无法接受的是pdo在mysql数据库上比mysqli慢。 - Thomas Williams
没关系。大多数PHP用户并不关心他们编写的代码量,所以你不是唯一一个发现mysqli可用的人。 - Your Common Sense
我曾经考虑转换到PDO,直到我发现PDO比mysqli慢6%,而一些额外的PHP代码对性能并不构成问题。如果您使用类编写代码并反复重用相同的代码,则这些额外的代码并不多。 - Thomas Williams
你测量差异的方式极其不准确。甚至不到0.6%。 - Your Common Sense

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接