2017-05-01 113 views
0

我有一个插入批量数据的脚本。这些数据大部分是前一个插入的复制,但至少有一个值是不同的。因此,我准备声明并将这些参数绑定执行并重复。PHP MySQL通过BATCH批量插入预准备语句

但是,我试图将它写入准备插入1000行顶部的批处理插入。不幸的是,我无法让它工作。我现在使用的代码只是一次插入整个数据。然而,这并不是想要的,因为数据量可能比测试的数量大得多。

我现在用的(批量插入一次全部)代码:

$Data = array(
    array("1", "2", "3", "4"), 
    array("1", "2", "3", "5"), 
    array("1", "2", "3", "6"), 
    array("1", "2", "3", "7"), 
    array("1", "2", "3", "8"), 
    //ETC 
    ); 
//AS YOU CAN SEE, ONLY COL4 CHANGES 
$sql = $mysqli->prepare("INSERT INTO `Table` (Col1, Col2, Col3, Col4) VALUES ".implode(', ', array_fill(0, count($Data), "(?, ?, ?, ?)"))); 
foreach ($Data as $InsertData) { 
    $sql->bind_param('iiii', $InsertData[0], $InsertData[1], $InsertData[2], $InsertData[3]); 
    } 
$sql->execute(); 

我想实现的是,该数据将像上面一份声明中可以插入,但有极限1000 (或任何其他编号)每批。我无法得到这个工作。我试图使用array_splice和其他方法,但我无法使它工作。

+0

可能重复的[MySQLi:插入多行与一个预准备语句](http://stackoverflow.com/questions/14860606/mysqli-inserting-multiple-rows-with-one-prepared-statement) – Ziinloader

回答

1

而不是试图加入阵列的任何更多的副本,你可以使用简单的for循环从细分工作:

$arraySize = count($Data); 
for ($i = 0; $i < $arraySize; $i+=1000) { 
    // Number of elements in this chunk 
    $thisChunk = min(1000, $arraySize-$i); 
    // Prepare your statement 
    $sql = $mysqli->prepare("INSERT INTO `Table` (Col1, Col2, Col3, Col4) VALUES ".implode(', ', array_fill(0, $thisChunk, "(?, ?, ?, ?)"))); 
    for($j = $i; $i < $i + $thisChunk; $j++) { 
    // Bind this data from $Data[$j] 
    } 
} 

当然会在每次重新准备你的说法,你能避免这种情况如果你知道thisChunk是1000个元素。

+0

我有一个问题。绑定返回'变量数量与准备语句中的参数数量不匹配'。这是因为在$ Data [$ j]'循环中,我一次绑定4个参数。我应该如何解决这个问题?例如。你能告诉我你如何期望我绑定'$ Data [$ j]'params? –

+1

你将不得不建立一个值的数组,并使用'call_user_func_array(array($ stmt,'bindparams'),$ array_of_params);'将它们全部链接到语句。另一种方法是转到PDO,在那里你可以一次连接一个PDO。 –

+0

谢谢PDO是要走的路!我现在可以在一个循环中绑定params并在完成时执行语句。谢谢! –

0

您应该考虑使用LOAD DATA INFILE。

即使您必须先写出一个临时文件,它也可能比使用批次行的INSERT快得多。

$Data = array(
    array("1", "2", "3", "4"), 
    array("1", "2", "3", "5"), 
    array("1", "2", "3", "6"), 
    array("1", "2", "3", "7"), 
    array("1", "2", "3", "8"), 
    //ETC 
    ); 

$tempname = tempnam("/tmp", "data"); 
$fp = fopen($tempname, "w"); 
foreach ($Data as $fields) { 
    fputcsv($fp, $fields); 
} 
fclose($fp); 
if ($mysqli->query(" 
    LOAD DATA INFILE '$tempname' INTO TABLE `Table` 
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' 
    ") === false) { 
    error_log($mysqli->error); 
} 
unlink($tempname); 

https://dev.mysql.com/doc/refman/5.7/en/load-data.html,以确保您了解有关LOCAL选项和local_infilesecure_file_priv配置选项。