前回に引き続き、Codeigniterの「update_batch」について説明していきます。
前回は、下記の様な例で「update_batch」の説明をしました。
$data = array( array( 'emp_id' => 'A001' , 'name' => 'koma taro' , 'tel' => '090-0000-1111' ), array( 'emp_id' => 'A002' , 'name' => 'koma saya' , 'tel' => '090-0000-2222' ) ); $this->db->update_batch('emptable', $data, 'emp_id');
「emptable」(社員テーブル)が更新対象のテーブル名、
「data」が更新&条件用の配列、
「emp_id」(社員ID)が更新時に条件として使用するカラムの指定、となります。
さて、ここで例えば、社員テーブルには、年度ごとにデータが格納されているとします。
(「year」(年度)というカラムがある)
つまり、2016年度と2017年度だけを考えても社員ID「A001」は2件存在する事になります。
でも、更新対象としたいのは2017年度のデータだけだとしたら・・・???
「$this->db->update_batch('emptable', $data, 'emp_id');」の第三引数は、
1つしか指定できません。
さて、困った、という事で、調べてみると、下記の情報が見つかりました。
stackoverflow - Codeigniter update_batch() with included update of the where key
上記のベストアンサーは、「Codeigniterのupdate_batchを拡張しないと無理だよ」と言っています。
さすがにそれは影響範囲大きいなぁ、と思っていたところ、ベストアンサー以外の回答で、
$this->db->where('option1', $option1); $this->db->update_batch('table_name', $data, 'option2');とあり、「これだったらお手軽だ」と思って、試してみました。
【注意】結論から言うと、上記では正常に動作しないので、決して真似しないで下さい。
$data = array( array( 'emp_id' => 'A001' , 'name' => 'koma taro' , 'tel' => '090-0000-1111' ), array( 'emp_id' => 'A002' , 'name' => 'koma saya' , 'tel' => '090-0000-2222' ) ); $this->db->where('year', '2017'); $this->db->update_batch('emptable', $data, 'emp_id');すると、生成されたSQLは、
UPDATE `emptable` SET `name` = CASE WHEN `emp_id` = 'A001' THEN 'koma taro' WHEN `emp_id` = 'A002' THEN 'koma saya' ELSE `name` END, `tel` = CASE WHEN `emp_id` = 'A001' THEN '090-0000-1111' WHEN `emp_id` = 'A002' THEN '090-0000-2222' ELSE `tel` END WHERE `year` = '2017' AND `emp_id` IN ('A001','A002')となり、年度の条件も付いているので、万々歳、と言う事で、
この方式を採用する事にしました。
やっぱりダメだった
ところが、しばらくして、この処理を実行すると、
2017年度のデータと一緒に、2016年度のデータも更新されている事が判明しました。
しかも、更新されない事もある、との事。
何度か試してみると、確かに生成SQLに「`year` = '2017'」が含まれていない事がありました。
ここで改めてリファレンスと読んでみると、
..note:: $batch_size より多くの行数が渡された場合、 複数のクエリが実行され、それぞれ $batch_size のフィールド/値ペア の分だけ操作を行う。とあります。
Codeigniter『データベースリファレンス - クエリビルダクラス - update_batch 』より。
・・・・「複数のクエリが実行される」???
先の例だと、例えば1000人の社員を一気に更新する際は、
単純に1000 ÷ batch_size(デフォルトは100)の 10 回クエリが実行されるようです。
しかも、
「$this->db->whereで指定した条件は、最初の1回目のクエリにしか反映されない」
という事のようです。
つまり、最初の1回目のクエリのみ2017年度の社員が更新されて、
2回目以降は2016年度と、2017年度の社員が両方更新されてしまっていたようです。
・・・・いや、どうせだったら、最初の1回目も条件反映しないでよ。
という事で、今回は「update_batch」を使うのをやめて、
「update」複数回実行する、という実装に変更しました。
・・・まあ、テーブル設計が杜撰なのは認めます。
きっと「update_batch」は、そういうテーブル設計を想定していないのだと思います。
「update_batch」を使う際は、ご注意下さい。
【追記】
タイトル詐欺になってしまうので、補足しておくと、基本は、「update_batch」で複数条件指定は出来ないと思います。
やるならば、先に記載した通り、
Codeigniterのupdate_batch(system/database/drivers/DB_query_builder.php)を
拡張する事になります。
ActiveRecord , CodeIgniter , PHP