来自多维数组的PHP PDO批量插入无法插入MySQL

时间:2013-10-10 12:02:29

标签: php mysql sql pdo bulkinsert

我有一个这样的数组,其中包含很多行,我需要使用PDO将其插入MySQL数据库

array(3067) {
  [0]=>
  array(2) {
    ["order"]=>
    string(7) "2854811"
    ["consignment"]=>
    string(0) ""
  }
  [1]=>
  array(2) {
    ["blah"]=>
    string(7) "2854811"
    ["whatever"]=>
    string(2) "someval"
  }
  [4]=>
  array(2) {
    ["blah"]=>
    string(7) "2864412"
    ["whatever"]=>
    string(0) ""
  }

我尝试了各种建议组合,但每条建议都会收到不同的错误消息

php PDO insert batch multiple rows with placeholders

PDO MySQL: Insert multiple rows in one query

我试过这个

$db->beginTransaction();

$stmt = $db->prepare("INSERT INTO mytable (column1, column2) VALUES (:blah, :whatever)");

foreach($test as $insertRow){

    // now loop through each inner array to match binded values
    foreach($insertRow as $column => $value){
        $stmt->bindParam(":{$column}", $value);
        $stmt->execute();
    }
}

$db->commit();

但我收到此错误消息

  

带有消息'SQLSTATE [HY093]的未捕获异常'PDOException':   参数号无效:绑定变量数不匹配   令牌数量

我也试过

$sql = 'INSERT INTO mytable (blah, whatever) VALUES ';
$insertQuery = array();
$insertData = array();
$n = 0;
foreach ($input as $row) {
    $insertQuery[] = '(:blah' . $n . ', :whatever' . $n . ')';
    $insertData['blah' . $n] = $row['blah'];
    $insertData['whatever' . $n] = $row['whatever'];
    $n++;
}

if (!empty($insertQuery)) {
    $sql .= implode(', ', $insertQuery);
    $stmt = $db->prepare($sql);
    $stmt->execute($insertData);
}

但是我得到这个错误信息,因为'blah'的每个长度是相同的

是没有意义的
  

带有消息'SQLSTATE [22001]的未捕获异常'PDOException':   字符串数据,右截断:1406列的数据太长   'order_number'在第1625行

如何让我的数组插入数据库?如果我必须执行一次加载或只需要执行一次,我就不会挑剔。

修改

我想要做的是在文本文件中读取并将其插入到一个完美运行的数组中,因此我所剩下的是一个约3000行的关联数组,它们每个都包含一个名为'blah'的字段'任何'。

获得数组后,我需要将其插入MySQL数据库

CREATE TABLE IF NOT EXISTS `tracker` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `blah` varchar(8) NOT NULL,
  `whatever` varchar(25) NOT NULL,
  `input_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

我最终应该从我的数组中插入大约3000行。

我希望这是有道理的。如果没有,我会再添加一些

1 个答案:

答案 0 :(得分:4)

我相信你几乎已经用这个例子了:

$db->beginTransaction();

$stmt = $db->prepare("INSERT INTO mytable (column1, column2) VALUES (:blah, :whatever)");

foreach($test as $insertRow){

   // now loop through each inner array to match binded values
   foreach($insertRow as $column => $value){
      $stmt->bindParam(":{$column}", $value);
      $stmt->execute();
   }
}

$db->commit();

您遇到的问题是在绑定适当数量的参数之前调用execute()。相反,您需要先绑定所有参数,然后调用execute()

$db->beginTransaction();

$stmt = $db->prepare("INSERT INTO mytable (column1, column2) VALUES (:blah, :whatever)");

foreach($test as $insertRow){

   // now loop through each inner array to match binded values
   foreach($insertRow as $column => $value){
      $stmt->bindParam(":{$column}", $value);
   }

}

// NOW DO EXECUTE
$stmt->execute();

$db->commit();

修改

在回应你的评论时,很难准确说出你想要完成什么,但如果你只收到一条记录,那么这是因为Gerald提出的,这些都是单独的查询,所有人都要立即交易。看看这个版本:

// Start Transaction
$db->beginTransaction();

// Insert each record
foreach($test as $insertRow){

   // Prepare statement
   $stmt = $db->prepare("INSERT INTO mytable (column1, column2) VALUES (:blah, :whatever)");

   // now loop through each inner array to match binded values
   foreach($insertRow as $column => $value){
      $stmt->bindValue(":{$column}", $value);
   }

   // Execute statement to add to transaction
   $stmt->execute();

   // Clear statement for next record (not necessary, but good practice)
   $stmt = null;
}

// Commit all inserts
$db->commit();