12

This should be SO simple. I want to retrieve the nextval of a sequence... it's not a default value... it's not a primary key... it's not a foreign key. In rare cases, I need a sequence number for a user supplied value.

I've tried the following:

@nextid = ActiveRecord::Base.connection.execute("SELECT nextval('xscrpt_id_seq')")

and what I get back is:

#<PG::Result:0x007fe668a854e8 @connection=#<PG::Connection:0x00000003aeff30>>

And by using

@nextid[0]["nextval"]

I can get the correct value, but it doesn't seem like the right way to approach the problem. I've searched, I read "Pro Active Record", which said to use:

M_script.find_by_sql("SELECT nextval('xscript_id_seq')")

but, that didn't work.

Any hints on the "correct" (Rails way) to retrieve a nextval from a sequence in ROR, would be very appreciated!

Ron
  • 437
  • 3
  • 12

4 Answers4

11

I believe:

ActiveRecord::Base.connection.execute( "SELECT nextval('xscrpt_id_seq')" )

is the correct solution. As I said in my original question, I checked the book "Pro Active Record" and it is their recommended solution. I'm still not exactly sure how ActiveRecord is making the connection, or if there's any maintenance I need to do (such as closing it).

ActiveRecord used to have a next_sequence_number method, but that has been deprecated.

Itay Grudev
  • 7,055
  • 4
  • 54
  • 86
Ron
  • 437
  • 3
  • 12
10

You probably want to use select_value and sequence_name:

Xscrpt.connection.select_value("select nextval('#{Xscrpt.sequence_name}')").to_i
kbrock
  • 958
  • 12
  • 15
  • select_value function is super helpful and no need to fetch like [0]['nextval']. Thanks @kbrock – Jagdish Aug 07 '20 at 17:54
  • 1
    You don't need the #to_i at the end, #select_value casts the value to Integer for you. – Jake Feb 06 '23 at 09:40
1

This works too:

 @seq = Smodelname.find_by_sql(" select seq_name.nextval as id from dual ")[0][:id]
Bacho sh
  • 56
  • 6
1

At least with Rails 5.1.7, be careful:

ActiveRecord::Base.connection.select_value

increments the sequence within a transaction only for the first call. When you execute it multiple times, you'll get always the same value and the sequence is not incremented.

ActiveRecord::Base.connection.execute

does not cache and works as expected