
Contents
Bulk Upsertとは
LaravelでBulk InsertやBulk UpdateならぬUpsert(既にあればUpdate,無ければInsert)も
バルクでやりたいという場面があった。
以下のBulk Insertのようなシンプルなコードからはほど遠くなったので言い訳をしたい。
(Bulk Insertの例)
$faker = Faker::create();
$params = [];
for ($i=0; $i < 10000; $i++) {
$params[] = [
'name' => $faker->name(),
'password' => $faker->password(),
];
}
User::insert($params);
Laravel8以上ではなかった。
Laravel8以上で開発をしている方、良かったですね。
Laravel8からはEloquent::upsertというメソッドが実装されたようです。
Laravel8の方は以上でreturnとなります。
Laravel 8.x Eloquentの準備
データを一様に変更する訳ではなかった。
Bulk UpsertやBulk Updateと言っても、ステータス的なカラムを一様に変更するか
それぞれ違うデータに変更するかで異なります。データを一様に変更するのは比較的簡単です。
Eloquentで絞り込めんでそのまま変えてしまえる場合は以下で済む。
これはそもそもBulkUpdateとわざわざ言うのか、よく分かりません。
User::where("name", "LIKE", "%Bob%")->update(['weight' => 'fat']);
また、フロントから配列を受け取る場合でもwherein句で済む。
$ids = $request['ids'];
User::wherein("id", $ids)->update(['age' => 'youth']);
updateOrCreateは複数データにどう使うか分からなかった。
updateOrCreateメソッドという変な名前のメソッドがあり、upsertとはきっとこれだと思ったが、
以下のように書いて、例えばA型のデータであれば性格は正直者となるとのこと。
A型の人がいなければUser自体を作るとのこと。
User::updateOrCreate(['blood_type' => 'A'], ['personality' => 'honest']);
複数の場合は更に[]で囲うんですかね、調べてもよく分からなかったので諦めました。
このメソッドをどのように複数に使うのか、もし知っていたら教えて欲しいです。
Laravel 5.7 Eloquent:利用の開始
データをそれぞれ変える場合はSQLを書くしかなかった。
結局はSQLでできることなのだから、DB::statementメソッドを使えば何とかなる通り。
SQLのInsert...ON DUPLICATE KEY)を作った配列でぶちこむことで凌げた。
Eloquentにできないこともsqlにはできる、生のsqlこそ至高!とはなりませんが、めでたしめでたし。
INSERT ... ON DUPLICATE KEY UPDATE 構文
foreach ($users as $user) {
//文字連結で見づらいが(user_id, user_name, user_status)を作りたいだけ。
$bulk_sql = $bulk.'('.$user->id.','.'$user->name,'.$user->status),';
}
//最後の行のカンマを抜く
$bulk_data = substr($bulk, 0, -1);
$sql_upsert = <<<SQL
INSERT INTO users (id, name, status)
VALUES
.$bulk_data.
ON DUPLICATE KEY
UPDATE
id = VALUES(id),
name = VALUES(name),
status = VALUES(status)
SQL;
// SQLの実行
DB::statement($sql_upsert);