views:

4699

answers:

8

Is there some way to get a value from the last inserted row?

I am inserting a row where the PK will automatically increase, and I would like to get this PK. Only the PK is guaranteed to be unique in the table.

I am using Java with a JDBC and PostgreSQL.

+4  A: 

The sequences in postgresql are transaction safe. So you can use the

currval(sequence)

Quote:

currval

Return the value most recently obtained by nextval for this sequence in the current session. (An error is reported if nextval has never been called for this sequence in this session.) Notice that because this is returning a session-local value, it gives a predictable answer even if other sessions are executing nextval meanwhile.

svrist
Isn't it possible that another transaction could change the value of the sequence between his INSERT and his SELECT currval() ? I'm assuming that each of those operations would take place in separate transactions.
matt b
No. that exactly what the currval function is for.
svrist
+1  A: 

Use sequences in postgres for id columns:

INSERT mytable(myid) VALUES (nextval('MySequence'));

SELECT currval('MySequence');

currval will return the current value of the sequence in the same session.

(In MS SQL, you would use @@identity or SCOPE_IDENTITY())

BradC
+4  A: 

PostgresSQL - RETURNING

INSERT INTO mytable( field_1, field_2,... ) VALUES ( value_1, value_2 ) RETURNING anyfield

It will return the value of "anyfield". "anyfield" may be a sequence or not.

Hope it helps

Luc M
+5  A: 

See the API docs for java.sql.Statement.

Basically, when you call executeUpdate() or executeQuery(), use the Statement.RETURN_GENERATED_KEYS constant. You can then call getGeneratedKeys to get the auto-generated keys of all rows created by that execution. (Assuming your JDBC driver provides it.)

It goes something along the lines of this:

Statement stmt = conn.createStatement();
stmt.execute(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet keyset = stmt.getGeneratedKeys();
Andrew Watt
+3  A: 

If you're using JDBC 3.0, then you can get the value of the PK as soon as you inserted it.

Here's an article that talks about how : https://www.ibm.com/developerworks/java/library/j-jdbcnew/

Statement stmt = conn.createStatement();
// Obtain the generated key that results from the query.
stmt.executeUpdate("INSERT INTO authors " +
                   "(first_name, last_name) " +
                   "VALUES ('George', 'Orwell')",
                   Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
if ( rs.next() ) {
    // Retrieve the auto generated key(s).
    int key = rs.getInt(1);
}
anjanb
Note that this won't work for Oracle (I'm using 10g)http://stackoverflow.com/questions/1976625/value-from-last-inserted-row-in-db
ian_scho
+1  A: 

Here is how I solved it, based on the answers here:

Connection conn = ConnectToDB(); //ConnectToDB establishes a connection to the database.
String sql = "INSERT INTO \"TableName\"" +
        "(\"Column1\", \"Column2\",\"Column3\",\"Column4\")" +
        "VALUES ('value1',value2, 'value3', 'value4') RETURNING 
         \"TableName\".\"TableId\"";
PreparedStatement prpState = conn.prepareStatement(sql);
ResultSet rs = prpState.executeQuery();
if(rs.next()){
      System.out.println(rs.getInt(1));
  }
eflles
A: 

Don't use SELECT currval('MySequence') - the value gets incremented on inserts that fail.

smilek
So what? He just asked for unique values, not contiguous values (which is an impossible goal in a system with parallel abortable transactions).
bortzmeyer
The original question: "Is there some way to get a value from the last inserted row?"Code that uses currval(seq) to form a SELECT statement for obtaining the last inserted row may fail to produce expected results.
smilek
A: 

Since PostgreSQL JDBC driver version 8.4-701 the PreparedStatement#getGeneratedKeys() is finally fully functional. We use it here almost one year in production to our full satisfaction.

In "plain JDBC" the PreparedStatement needs to be created as follows to make it to return the keys:

statement = connection.prepareStatement(SQL, Statement.RETURN_GENERATED_KEYS);

You can download the current JDBC driver version here (which is at the moment still 8.4-701).

BalusC