LoginSignup
11
4

More than 5 years have passed since last update.

activerecord-importでユニークキー制約に引っかかるようにする

Last updated at Posted at 2017-02-04

activerecord-import でバルクインサートした際にデフォルトだとテーブルに設定したユニークキー制約に引っかからない事象が起きたので、その原因と解決策を書きます。

バージョン

  • activerecord-import: 0.16.2
  • activerecord: 5.0.1
  • MySQL: 5.7.12

tl;dr

  • .import メソッドを使う時に on_duplicate_key_update: false する

起きた事象

ユニークキー制約をかけたテーブルのモデル Hoge に対してバルクインサートの処理を書いていました。
コードだと以下のようなものです。

hoges = params[:hoges].map do |hoge_params|
  Hoge.new(inspect_create_hoge_params(hoge_params))
end
Hoge.import(hoges)

制約に引っかかっているデータが送られてきた時は例外が発生することを期待していたのですが、実際やってみると最初の1件だけ保存されるという動きをしていました。

原因

発行されているSQLのログを見ると、

INSERT INTO `hoges` 
(~~中略~~) 
ON DUPLICATE KEY UPDATE `hoges`.`updated_at`=VALUES(`updated_at`)

ON DUPLICATE KEY UPDATE が怪しいなと思いリファレンスを調べてみると、

If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUE index or PRIMARY KEY, MySQL performs an UPDATE of the old row.

ユニークキー制約にかかったレコードを保存する時に古いレコードをupdateする、というまさに今起こっていた動きが書いてありました。

解決策

コードを追いかけてみた結果、 on_duplicate_key_update をfalseにしたら ON DUPLICATE KEY UPDATE をしないように見えたので、

Hoge.import(hoges, on_duplicate_key_update: false)

としてみたところ、期待した例外が発生するようになりました。SQLの方も

INSERT INTO `hoges` 
(~~中略~~) 

ON DUPLICATE KEY UPDATE が消えていることも確認できました。

11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4