basyura's blog

あしたになったらほんきだす。

レコード追加時に AUTOINCREMENT なフィールドの値を取得する

rails でよくやる関連のあるテーブルで親と子を一緒に保存するような場合に、自動インクリメントされる親の ID の値をどうやって取得して子にセットしてるのか気になって調べてみた。

last_inserted_id

各 adapter の last_inserted_id を使っているようだ。

  • gems/activerecord-4.1.5/lib/active_record/connection_adapters/mysql2_adapter.rb
def last_inserted_id(result)
  @connection.last_id
end
  • gems/activerecord-4.1.5/lib/active_record/connection_adapters/postgresql_adapter.rb
def last_insert_id_result(sequence_name) #:nodoc:
  exec_query("SELECT currval('#{sequence_name}')", 'SQL')
end
  • gems/activerecord-4.1.5/lib/active_record/connection_adapters/sqlite3_adapter.rb
def last_inserted_id(result)
  @connection.last_insert_row_id
end

sqlite では SQL 実行で取得できるっぽい (テーブルを指定しないと他のテーブルの値が返ってくることがあるとかなんとか)。

select * from tablename where ROWID = last_insert_rowid();

試しに sqlite を使ってみる

require 'sqlite3'

db = SQLite3::Database.new 'development.sqlite3'

db.transaction do
  p  db.execute "insert into users values ( ?, ?, ?, ?)", [nil, 'basyura', '2014-08-27', '2014-08-27' ]
  #p  db.execute "select id from users where ROWID = last_insert_rowid()"
  p db.last_insert_row_id
end

いけた。