10

在使用 AWS Redshift 时,我注意到通过 JDBC 驱动程序从具有标识列的表中获取最后插入的 id 无法使用以下任一方法完成:

RETURNING key word

或者

Statement.RETURN_GENERATED_KEYS 

如堆栈溢出条目中所述:

如何从最后插入的行中获取值?

上述方法不可用,因为 Redshift(截至 2013 年 10 月 17 日)是在 PostgreSQL 版本 8.0.2 上构建的。请参阅以下链接中的以下文档:

http://docs.aws.amazon.com/redshift/latest/dg/c_high_level_system_architecture.html

如果您打算将 Redshift 用作 RDBMS,那么阅读以下内容也是值得的:

http://docs.aws.amazon.com/redshift/latest/dg/c_redshift-and-postgres-sql.html

问题:

通过 PostgreSQL JDBC 驱动程序在 Redshift 中的自动增量/序列/标识列上检索最后插入的 id 的最佳策略是什么?

4

1 回答 1

4

鉴于 Redshift 引擎是在 PostgreSQL 8.0.2 上构建的,并且上述 RETURNING 和 Statement.RETURN_GENERATED_KEYS 选项不可用并且 Redshift 不支持 CREATE SEQUENCE 以使用 CURRVAL/NEXTVAL 函数套件,一个选项是将两个 SQL 语句分组JDBC 事务中的 INSERT 和 SELECT MAX([identity column]) 一起。

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) {

    }
}

如果 SQL_INSERT_STATEMENT 写入/锁定单个表,则上述方法将起作用。多个表锁需要一个 synchronized 关键字来防止死锁。在锁定的表上进行选择将允许在 ResultSet 中返回递增的标识值。

于 2013-10-17T14:01:53.727 回答