【问题标题】:MySQL, MySQLi, MySQL Prepared Statement or PDO? [duplicate]MySQL、MySQLi、MySQL Prepared Statement 还是 PDO? [复制]
【发布时间】:2011-06-26 10:47:46
【问题描述】:

在过去的几天里,我一直在关注很多关于与数据库交互的不同方式的教程。像旧的 MySQL 方式,MySQLi,MySQLprepared statement,PHP 的 PDO 等。

我仍然是编程的新手,因为我学习并开始编码还不到 1 年。我不时地在改进我的代码和遵守 Web 开发人员定义的标准方面付出了很多努力。现在是时候让我觉得我改变了使用旧 MySQL 方式(如 mysql_connect() 和 mysql_query())与数据库交互的方式。

我的生产机器上有以下配置。

  • 安装了 MAMP 的 Mac OSX 10.6
  • PHP 版本:5.2.13
  • MySQL 客户端版本:5.1.44

你认为我应该使用什么来访问数据库,为什么?

  • MySQL
  • MySQLi
  • MySQL 准备好的语句
  • PDO

【问题讨论】:

    标签: php mysql database pdo mysqli


    【解决方案1】:
    • Mysql ext 已不复存在。
    • 假设MySQL Prepared StatementSQL implementation,我发现它在PHP 中几乎不可用

    这让我们只有两个可能的选择

    • PDO。如果您打算按原样使用数据库 API,那么 PDO 是明显的赢家,它比 mysqli 更加用户友好。此外,如果您正在编写一个开源库,那么 PDO 是唯一的选择,因为它可以让用户连接任何支持的数据库。总而言之,PDO 是一个很好的经验法则:如果您不知道要使用哪个驱动程序,请直接使用 PDO。
    • mysqli。如果您要编写一个数据库包装器来封装原始 API 函数,并且您的数据库后端将始终保持 mysql 并且命名参数对您来说不是一个游戏规则改变者,那么 mysqli 也可能是一个不错的选择,它提供了一些方便的 mysql-specific mysqli_info() 等函数。

    【讨论】:

    • "而且 PDO 比 mysqli 好得多" PDO 在可用时使用 MySQLi 扩展。界面可能会更好,但这也是品味问题。
    • PDO 不以任何方式使用 mysqli。两者都是 Mysql C API 的包装器
    【解决方案2】:

    PDO for MySQL 与直接使用 MySQLi 相比有几个主要优势。

    1. PDO 支持多个数据库后端。如果您的一个客户请求将您的应用程序移植到不同的数据库,这会有所帮助。
    2. 除了 MySQLi 支持的位置 (?) 占位符之外,PDO 中的准备好的语句还支持命名占位符。
    3. PDO 支持一次绑定单个参数,而不是一次绑定所有参数。这允许单步执行一组参数并绑定每个参数,而不必构造一个类型字符串然后使用call_user_func_array() 黑魔法。
    4. PDO 通过将数组传递给$stmt->execute() 来支持便捷的快捷方式,其中每个键的值都绑定到占位符作为键。 (警告:它将每个值转换为一个字符串,所以你必须bind one at a time if your statement has a variable LIMIT。这是documented,还有一个feature request to change this casting to string。)

    第 2 到 4 项结合起来,非常更容易以可证明的注入安全方式表达运算符 IN 的右侧。使用 PDO,您可以构建一个具有连续名称的关联数组(例如 [':likeval0'=>$val0, ':likeval1'=>$val1, ':likeval2'=>$val2]),然后在该数组的右侧安全地构建一个占位符列表。代码可能如下所示:

    $args = [];
    foreach ($usernames as $n=>$value) {
        $args[":likeval$n"] = $value;
    }
    $list = implode(',', array_keys($args));
    // result is like ':likeval0,:likeval1,:likeval2'
    $stmt = "SELECT * FROM app_users WHERE `username` IN ($list)";
    $stmt = $dbh->prepare($stmt);
    $c = $stmt->execute($args);
    

    MySQLi 仅支持? 占位符和通过变量参数函数调用的一次性绑定。在 MySQLi 中,通过对列表中的每个元素使用 $dbh->escape_string(),构造运算符 IN 的右侧实际上要容易得多。如果经过良好测试,这种方法对 SQL 注入是安全的,但会引发一些 "Bobby Tables" parameterization purists 的危险信号。

    【讨论】:

      【解决方案3】:

      这真的取决于你在做什么。

      如果您正在执行大量使用预准备语句的大量查询,预准备语句(通过 mysqli 或 PDO)可能会很有用。准备好的语句更快,此外,您不必担心使用准备好的语句转义数据之类的事情,但是它们会占用一些代码开销,因此对于一个简单的应用程序,有时不值得使用准备好的语句并使用旧的 mysql_* 函数是更容易达到预期目的。

      【讨论】:

        猜你喜欢
        • 2011-07-24
        • 1970-01-01
        • 2013-04-18
        • 2012-08-18
        • 2014-10-23
        • 2021-10-01
        • 2011-10-21
        • 2014-11-04
        相关资源
        最近更新 更多