2017-05-01 149 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配置選項。