[英]php PDO insert batch multiple rows with placeholders
我希望使用PHP PDO進行多次插入。
我找到的最接近的答案是這一個
然而,給出的例子使用?? 而不是真正的占位符。
我查看了PHP文檔站點上的占位符示例
php.net pdo.prepared-statements
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
現在讓我說我想實現上述但是使用數組
$valuesToInsert = array(
0 => array('name' => 'Robert', 'value' => 'some value'),
1 => array('name' -> 'Louise', 'value' => 'another value')
);
如何使用PDO和每次交易多次插入?
我想它會以循環開始?
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow){
// now loop through each inner array to match binded values
foreach($insertRow as $column => value){
$stmt->bindParam(":{$column}", value);
}
}
$stmt->execute();
然而,上述情況不起作用,但希望能夠展示我想要實現的目標
首先, ?
符號是真正的占位符(大多數驅動程序允許使用語法,位置和命名占位符)。 其次,准備好的語句只不過是將原始輸入注入SQL語句的工具 - SQL語句本身的語法不受影響。 您已經擁有了所需的所有元素:
將它們全部組合在一起是相當微不足道的:
$sql = 'INSERT INTO table (memberID, programID) VALUES ';
$insertQuery = array();
$insertData = array();
$n = 0;
foreach ($data as $row) {
$insertQuery[] = '(:memberID' . $n . ', :programID' . $n . ')';
$insertData['memberID' . $n] = $memberid;
$insertData['programID' . $n] = $row;
$n++;
}
if (!empty($insertQuery)) {
$sql .= implode(', ', $insertQuery);
$stmt = $db->prepare($sql);
$stmt->execute($insertData);
}
我假設您正在使用InnoDB,因此此答案僅對該引擎(或任何其他具有事務功能的引擎有效,意味着不包括MyISAM)。
默認情況下,InnoDB以自動提交模式運行。 這意味着每個查詢都被視為自己包含的事務。
要將其轉換為我們凡人可以理解的內容,這意味着您發出的每個INSERT查詢都會強制硬盤通過確認它寫下查詢信息來提交它。 考慮到機械硬盤如何超慢,因為它們每秒的輸入輸出操作很低(如果我沒有記錯,平均值是300的IO),這意味着你的5萬個查詢將會 - 超級慢。
所以你會怎么做? 您在一次交易中提交所有50k查詢。 它可能不是用於各種目的的最佳解決方案,但它會很快。
你這樣做:
$dbh->beginTransaction();
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow)
{
// now loop through each inner array to match bound values
foreach($insertRow as $column => value)
{
$stmt->bindParam(":$column", value);
$stmt->execute();
}
}
$dbh->commit();
NB提供的解決方案稍作修改
$ stmt-> execute()應該在內部循環之外,因為在調用$ stmt-> execute()之前你可能有一個或多個需要綁定的列,否則你將獲得異常“無效的參數編號:綁定變量的數量確實不匹配令牌數“。
第二個“價值”變量缺少美元符號。
function batchinsert($sql,$params){
try {
db->beginTransaction();
$stmt = db->prepare($sql);
foreach($params as $row)
{
// now loop through each inner array to match bound values
foreach($row as $column => $value)
{
$stmt->bindParam(":$column", $value);
}
$stmt->execute();
}
db->commit();
} catch(PDOExecption $e) {
$db->rollback();
}
}
測試:
$sql = "INSERT INTO `test`(`name`, `value`) VALUES (:name, :value)" ;
$data = array();
array_push($data, array('name'=>'Name1','value'=>'Value1'));
array_push($data, array('name'=>'Name2','value'=>'Value2'));
array_push($data, array('name'=>'Name3','value'=>'Value3'));
array_push($data, array('name'=>'Name4','value'=>'Value4'));
array_push($data, array('name'=>'Name5','value'=>'Value5'));
batchinsert($sql,$data);
你的代碼實際上沒問題,但在$stmt->bindParam(":$column", value);
遇到了問題$stmt->bindParam(":$column", value);
它應該是$stmt->bindValue(":{$column}", $value);
它會很完美。 這將在未來幫助其他人。
完整代碼:
foreach($params as $row)
{
// now loop through each inner array to match bound values
foreach($row as $column => $value)
{
$stmt->bindValue(":{$column}", $value); //EDIT
}
// Execute statement to add to transaction
$stmt->execute();
}
在循環內移動執行。
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow)
{
$stmt->execute($insertRow);
}
如果您遇到這種推薦方式的任何問題,您必須提出一個問題,描述這些問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.