【问题标题】:Inserting multiple rows (single query) to MySQL in PHP: Prepare-Execute vs. Prepare-Bind-Execute在 PHP 中向 MySQL 插入多行(单个查询):Prepare-Execute 与 Prepare-Bind-Execute
【发布时间】:2015-05-04 18:55:41
【问题描述】:

我正在编写一些 PHP 来接受 POST 中的数字和名称数组并将它们插入 MySQL 表(名为 Contacts_table ) 这是可以正常工作且没有任何错误的版本:

<?php

  // Includes
  require_once 'Admin/Connector.php';

  // Test if payload exists
  if($_POST){

  // Read payload into arrays
      $ar = 0;
      foreach($_POST as $entry){
          $namenum = explode(',', $entry);
          $names[$ar] = $namenum[1];
          $numbers[$ar] = $namenum[0];
          $ar += 1;
      }
      $namenum = NULL;

  // Build SQL query
      $sql = 'INSERT INTO Contact_table (NAME, PHONE) VALUES ';
      $insertQuery = array();
      $insertData = array();
      $n = 0;
      foreach ($numbers as $num) {
        $insertQuery[] = '(?, ?)';
        $insertData[] = $names[$n];
        $insertData[] = $num;
        $n++;
      }
      $sql .= implode(', ', $insertQuery);
      $sql .= ' ON DUPLICATE KEY UPDATE name = COALESCE(VALUES(name), name);';
      $n = NULL;
      $num = NULL;

  // Connect to MySQL database
      $connect = dbconn(PROJHOST,PROJDB,PROJDBUSER,PROJDBPWD);

  // Execute SQL query
      $query = $connect->prepare($sql);
      $query->execute($insertData);
      $insertQuery = NULL;
      $insertData = NULL;
      $sql = NULL;
      $query = NULL;

  // Close connection to MySQL database
      $connect = NULL;

  }

?>

但是,如您所见,我在这里没有使用 bindParam() 函数,只是将值直接提供给 execute() 函数。许多人建议我使用 bindParam() 来提高服务器性能。是真的还是我对这个程序更好?我确实尝试使用 bindParam 编写和运行上述代码的一个版本:

<?php

  // Includes
  require_once 'Admin/Connector.php';

  // Test if payload exists
  if($_POST){

  // Read payload into arrays
      $ar = 0;
      foreach($_POST as $entry){
          $namenum = explode(',', $entry);
          $names[$ar] = $namenum[1];
          $numbers[$ar] = $namenum[0];
          $ar += 1;
      }
      $namenum = NULL;

  // Build SQL query
      $sql = 'INSERT INTO Contact_table (NAME, PHONE) VALUES ';
      $insertQuery = array();
      $insertData = array();
      $n = 0;
      foreach ($numbers as $num) {
        $insertQuery[] = '(?, ?)';
        $insertData[] = $names[$n];
        $insertData[] = $num;
        $n++;
      }
      $sql .= implode(', ', $insertQuery);
      $sql .= ' ON DUPLICATE KEY UPDATE name = COALESCE(VALUES(name), name);';
      $n = NULL;
      $num = NULL;

  // Connect to MySQL database
      $connect = dbconn(PROJHOST,PROJDB,PROJDBUSER,PROJDBPWD);

   // Prepare SQL query 
      $query = $connect->prepare($sql);

  // Bind variables
      foreach($insertData as $key => &$ins) {
          $connect->bindParam($key+1,$ins);
      }

  // Execute SQL query
      $query->execute();
      $insertQuery = NULL;
      $insertData = NULL;
      $sql = NULL;
      $query = NULL;
      $key = NULL;
      $ins = NULL;

  // Close connection to MySQL database
      $connect = NULL;

  }

?>

但是这段代码拒绝运行并返回一个致命错误——调用未定义的方法 PDO::bindParam()。我在这里做错了什么?我知道如果我在循环中包含 execute() 可以编写更简单的代码,但这会产生多个我想不惜一切代价避免的查询。无论如何,我的目标是单个查询。

【问题讨论】:

  • 我认为没有任何效率提升,但我从未对此类比较进行基准测试。
  • 关于“如果在循环中执行更简单的代码”:根据我在其他 (.Net) 语言中的经验,只要“准备好”查询,多次执行与“批量”之间的性能差异可以忽略不计" 插入查询。多执行还有其他好处,比如不必担心查询本身对您的连接器来说太长了。
  • ...“查询本身”是指查询字符串。
  • @uueerdo 感谢您的解释。但是,抛开性能提升不谈,许多托管服务提供商不是对您每天可以执行的交易数量规定了一定的上限吗?我记得最近在 Amazon Cloud 的网站上读到,他们按交易向您收费,尽管上限很高,而且他们提供 MongoDb。不确定 Mysql 主机是做什么的。这是我唯一的担心。
  • @AmitSchandillia,我不熟悉托管费率;我所做的所有开发都是基于“内部”服务器。我可以想象试图围绕这些限制进行开发会令人沮丧。我认为/希望这样的主机不一定会定义 1 个查询 = 1 个事务;但就像我说的,我非常不熟悉这些限制。 (也许如果您以“START TRANSACTION;”开始查询集并以“END TRANSACTION;”结束它们?)

标签: php mysql pdo prepared-statement prepare


【解决方案1】:

你不能$connect-&gt;bindParam($key+1,$ins);。因为 PDO 对象没有这样的方法。只有 PDOStatement 有。这就是您收到错误消息的原因。

你应该:

 $query->bindValue($key+1,$ins);

你应该使用bindValue,因为如果不是这样,你所有插入的值都会得到相同的值(在你调用execute之前的最后一个$ins)。

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 2012-04-24
    • 2012-07-08
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 2018-01-23
    相关资源
    最近更新 更多