While working with AWS Redshift is has come to my attention getting the last inserted id from a table with an identity column via JDBC driver cannot be accomplished with either of the following methods:
RETURNING key word
or
Statement.RETURN_GENERATED_KEYS
as mentioned in the Stack Overflow entry:
How to get a value from the last inserted row?
The above methods are not available as Redshift (as of 10/17/2013) is built on PostgreSQL version 8.0.2. See the following documentation in the following link:
http://docs.aws.amazon.com/redshift/latest/dg/c_high_level_system_architecture.html
If you are intending to use Redshift as a RDBMS it is a worthwhile effort to read the following as well:
http://docs.aws.amazon.com/redshift/latest/dg/c_redshift-and-postgres-sql.html
Question:
What is the best strategy for retrieving the last inserted id on an auto-increment/serial/identity column in Redshift via PostgreSQL JDBC driver?
Given the Redshift engine is built on PostgreSQL 8.0.2 and the above RETURNING and Statement.RETURN_GENERATED_KEYS options are not available AND Redshift does not support CREATE SEQUENCE for the use of the CURRVAL/NEXTVAL function suite, one option would be to group two SQL statements together, INSERT and SELECT MAX([identity column]) in a JDBC transaction.
try {
// create the JDBC connection
Class.forName(JDBC_DRIVER);
Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
// start the transaction
conn.setAutoCommit(false);
// create the prepared statement for insert
PreparedStatement prpd = conn.prepareStatement(SQL_INSERT_STATEMENT);
// set input/output parameters as needed...
// execute the SQL prepared statement
int j = prpd.executeUpdate();
// create a statement for select max()
Statement stmt = conn.createStatement();
// execute the statement to return a result set
ResultSet key = stmt.executeQuery(SQL_SELECT_MAX_STATEMENT);
// initialize and retrieve the incremented identity value, in this case it is a long (bigint data type in Redshift)
long id = 0;
if (key.next()) {
id = key.getLong(1);
}
// commit the entire transaction
conn.commit();
} catch (SQLException se) {
// if an SQL exception occurs, rollback the whole deal
try {
if (conn!=null && !conn.isClosed()) {
conn.rollback();
}
} catch (Exception e) {
}
} catch (Exception e) {
// roll back if something other than an SQLException occurs
try {
if (conn!=null && !conn.isClosed()) {
conn.rollback();
}
} catch (Exception e) {
}
} finally {
// do whatever you want to return a value, shut down resources
// close out JDBC resources
try {
if (conn!=null && !conn.isClosed()) {
conn.setAutoCommit(true);
}
} catch (SQLException se) {
}
try {
if (prpd!=null && !prpd.isClosed()) {
prpd.close();
}
} catch (SQLException se) {
}
try {
if (stmt!=null && !stmt.isClosed()) {
stmt.close();
}
} catch (SQLException se) {
}
try {
if (conn!=null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException se) {
}
}
The above will work if the SQL_INSERT_STATEMENT writes to/locks a single table. Multiple table locks will require a synchronized keyword to protect against deadlock. Selecting on a locked table will allow for the incremented identity value to be returned in a ResultSet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With