10

AWS Redshift を使用しているときに、JDBC ドライバーを介して ID 列を持つテーブルから最後に挿入された 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 列に最後に挿入された ID を取得するための最良の戦略は何ですか?

4

1 に答える 1

4

Redshift エンジンが PostgreSQL 8.0.2 上に構築されており、上記の RETURNING および Statement.RETURN_GENERATED_KEYS オプションが利用できず、かつ Redshift が CURRVAL/NEXTVAL 関数スイートの使用に対して CREATE SEQUENCE をサポートしていない場合、1 つのオプションは 2 つの 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 キーワードが必要です。ロックされたテーブルを選択すると、インクリメントされた ID 値が ResultSet で返されます。

于 2013-10-17T14:01:53.727 に答える