$wpdb->prepareで配列を使ってDBに一括登録・バルクインサート

2019-04-26WordPressSQL

csvファイルから読み込んだデータをゴニョゴニョしてから、$wpdb(Wordpressのデータベースを操作するクラス)のプレースホルダーを使って一気に登録する方法

やりたいこと

バルクインサートとは、1回のInsert処理で複数のデータを登録することができる
何度もSQL文を実行しなくていい、どこかの行で失敗したら全部ロールバックされるのでもう一度やり直せばいい。
(csv読み込みのため、途中で失敗して、失敗したところから登録処理を開始するより始めからやり直したほうが簡単そう)

INSERT INTO table (col1, col2, col3)
VALUES ( 'hoge1', 'koge1', 'hage1' ), ('hoge2', 'koge2', 'hage2'), ('hoge3', 'koge3', 'hage3');
こんなのを$wpdb->prepareを使って実行したい

方法


global $wpdb;
// プレースホルダーとインサートするデータ配列
$arrayValues = array();
$place_holders = array();
// $recordsはインサートするデータが入ってる(ここでいうcsvの値をゴニョゴニョした結果)
foreach ($records as $row) {
  // インサートするデータを格納
  $arrayValues[]=$row['col1'];
  $arrayValues[]=$row['col2'];
  $arrayValues[]=$row['col3'];
  // array_pushを使ってもできるけど、処理速度はかなり遅くなる
  // array_push($arrayValues, row['col1'], row['col2'], row['col3']);
  // プレースホルダーの作成
  $place_holders[] = '(%s, %s, %s)';
}
// SQLの生成
$sql = 'INSERT INTO table (col1, col2, col3) VALUES '.join(',', $place_holders);
// SQL実行
if ($wpdb->query($wpdb->prepare($sql, $arrayValues))) {
    echo '成功';
} else {
    echo '失敗';
}

* プレースホルダーは、インサートする行の数だけ用意しなくてはならない
* array_pushは超絶遅い。array[]と比較すると、500個くらいの要素数でも1.5倍以上遅い
* プレースホルダーの'%s'は文字列(String)、数値型(int)の場合は'%d'にする

Posted by Agopeanuts