将多行(单个查询)插入 PHP 中的 MySQL:Prepare-Execute 与 Prepare-Bind-Execute

Inserting multiple rows (single query) to MySQL in PHP: Prepare-Execute vs. Prepare-Bind-Execute

我正在写一些 PHP 来接受 POST 中的数字和名称数组,并将它们插入 MySQL table(命名为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;

  }

?>

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

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

你应该:

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

并且您应该使用 bindValue,因为否则,所有插入的值都将获得相同的值(调用 execute 之前 $ins 的最后一个值)。