LoginSignup
21
15

More than 3 years have passed since last update.

activerecord-importでon_duplicate_key_updateを忘れたときの挙動

Last updated at Posted at 2018-09-21

2019/07/11 追記
この挙動ですが、v1.0.0以降のversionでは修正されているようです。
記事作成時に利用していたversionは0.27.0でした。

@kikunantoka さん ご指摘ありがとうございました!


RailsでRDBのレコードを一括処理したいときにactiverecord-importを使っていたのですが、
うまくデータ更新されてないものが見つかったので調査した結果の覚書です。
(RDBMSがMySQLの場合の話です)

on_duplicate_key_update

bulk_insertする際、新規レコードは作成、そうでないものは更新してくれるオプション。
activerecord-importでも対応しています。
https://github.com/zdennis/activerecord-import/wiki/On-Duplicate-Key-Update

which allows you to specify fields whose values should be updated if a primary or unique key constraint is violated.

とあるように、主キー / ユニークキー制約に引っかかった場合、対象レコードの指定したカラムの値だけ更新してくれます。

Foo.import [foos], on_duplicate_key_update: [:col1, :col2]

間違っていた部分とその結果

作成 / 更新の両方があり得るテーブルに対して、on_duplicate_key_updateオプションを指定せずにimportしていました。

Foo.import [foos]

この場合、例外処理が起きるか、更新されずに放置されるかだと思っていたのですが、最終更新日時(updated_at)のカラムだけが更新されるようです。

INSERT INTO `foos` (`id`, `col1`, `col2`, ..., `created_at`, `updated_at`)
VALUES (...)
ON DUPLICATE KEY UPDATE `foos`.`updated_at` = VALUES(`updated_at`)

結果として、更新はされている(ように見える)がカラムの値は何も変わっていないレコードが生まれていました。
on_duplicate_key_updateオプションを指定したら正常に更新されるようになりました。一安心。

21
15
2

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
21
15