せたがやえんじにあぶろぐ

Ruby | Rails | iPhone | Web

PostgreSQLとRailsでシーケンスを手動で上げる

通常RailsActiveRecordでレコードを作成するときは

User.create(name: "なまぽ", email: "namapo@mailaddress.com")

などとして作成し、テーブルのprimary_keyがidになっている場合には

自動でidを付与してシーケンスも自動インクリメントしてくれるので、

コードを書いている時に、idに関する考慮をあまりしなくてもいい仕組みになっているよ。

migrateなどで、テーブルを作成した場合にも特に指定がなければ

idのカラムを自動で作成してくれるし、さらにidのprimary_key指定もやってくれる。


例外として、idの順序やidそのものに意味がある場合には稀に

User.create(id: 1, name: "なまぽ1", email: "namapo1@mailaddress.com")

みたいに、idを指定してレコードを作成する場面があるかもしれない。

上みたいに、idを指定した場合にはシーケンスが自動でインクリメントしないので、

次に

User.create(name: "なまぽ2", email: "namapo2@mailaddress.com")

のように、次のレコードをid指定しないで作成した場合にエラーで怒られてレコードが作成できない。

PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "users_pkey"
DETAIL:  Key (id)=(1) already exists.

こんな時には手動でシーケンスを上げてあげる必要がある。

SELECT setval('users_id_seq', coalesce((SELECT MAX(id)+1 FROM users), 1), false)

このSQLを実行することで、現在テーブルに格納されているレコードのidの最大値を取得して、

それに + 1したものをシーケンスとして保存してくれます。

うえのコードをRails上から呼び出す場合には

ActiveRecord::Base.connection.execute("SELECT setval('users_id_seq', coalesce((SELECT MAX(id)+1 FROM users), 1), false)")

してあげれば良しです。

ActiveRecord::Base.connection.execute()

の引数に任意のSQLを記述すれば実行できる