ActiveRecordのinsert_all
概要
insert_all / insert_all!
複数のレコードを単一のSQLクエリで挿入する(バルクインサート)
大量データの挿入を効率的に行いたい場合や、重複キーを許容しつつ新しいレコードのみを挿入したい場合に使おう
/icons/point.icon直接SQLを発行するのでバリデーションやコールバックをスキップする
これにより、パフォーマンスが向上しますが、データの整合性を確保するために、事前にデータの検証が必要
/icons/point.iconデフォルトで主キー(通常はid)が重複した場合、そのレコードをスキップします
挿入されたレコードの情報を返さない
挿入に失敗したレコードの情報を直接取得する機能はない
メソッド引数
モデル.insert_all(属性, returning: nil, unique_by: nil, record_timestamps: nil)
:returning
操作後に戻されるカラムを指定します。特定のカラムの値を取得するために使用されます。
例: returning: [:id, :updated_at]
:unique_by
指定したキーで重複した場合はinsertスキップする
:record_timestamps
タイムスタンプの自動設定を強制
発行されるSQL
code:sql
INSERT INTO users (name, age) VALUES
('Alice', 25),
('Bob', 30),
('Charlie', 35)
ON DUPLICATE KEY UPDATE id = id;が末尾に付与される
「行が重複して挿入できない場合、既存のidカラムの値でidカラムの値を上書きする、つまり 何も更新しない ということになる
「重複レコードをスキップ」するために付与される
例
code:ruby
# ActiveRecordでのinsert_allの基本的な使用例
records = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 35 }
]
User.insert_all(records)
code:ruby
users = (1..100).map { { name: "name", email: "hoge@hoge.com", created_at: Time.current, updated_at: Time.current } }
User.insert_all(users, returning: %iid name) # idとnameのみ返す code:ruby
inserted_records = User.insert_all(
[
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Alice', email: 'alice2@example.com' } # 意図的に重複
],
unique_by: :email, # email列で一意制約
returning: :email # 挿入されたレコードのemailを返す
)
failed_records = [
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Alice', email: 'alice2@example.com' }
] - inserted_records
/icons/hr.icon