2016-01-07 33 views
13

更新文の選択を実行しようとしたときに奇妙な問題が発生し、その後に挿入または更新を実行します。 ORA-01461例外が発生します。これは、最新のojdbcドライバ(12.1.0.2)を使用している場合にのみ発生し、古いものではうまく動作します(12.1.0.1)。PreparedStatement +主キー列のOracle 12c + ORA-01461の選択

より具体的には、対応する列が32文字を超えて宣言されているにもかかわらず、最新のドライバでは主キー文字の長さに制限があるようです(32文字に制限されています)。問題を複製するためのサンプルコードは以下の通りです:

CREATE TABLE "TEST_TABLE" (
"TEST_ID" VARCHAR2(40 CHAR) NOT NULL ENABLE, 
"TEST_COMMENT" VARCHAR2(200 CHAR), 
CONSTRAINT "TEST_TABLE_PK" PRIMARY KEY ("TEST_ID") 
); 

そして、いくつかのjava:メインメソッドの

public class DemoUpdatableResultSet { 

    private static final String DB_URL = "jdbc:oracle:thin:@xxxx:1521/xxxxx"; 
    private static final String DB_USER = "xxx"; 
    private static final String DB_PASS = "xxx"; 

    public static Connection getConnection() throws Exception { 
    Class.forName("oracle.jdbc.driver.OracleDriver"); 
    Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS); 
    return conn; 
    } 

    public static void main(String[] args) { 
    final String uuid = UUID.randomUUID().toString(); 
    ResultSet rs = null; 
    Connection conn = null; 
    PreparedStatement pstmt = null; 
    try { 
     conn = getConnection(); 
     String query = "SELECT t.* FROM TEST_TABLE t WHERE t.TEST_ID=? FOR UPDATE"; 
     pstmt = conn.prepareStatement(query, ResultSet.TYPE_SCROLL_SENSITIVE, 
      ResultSet.CONCUR_UPDATABLE); 
     pstmt.setString(1, uuid); // set input values 
     rs = pstmt.executeQuery(); // create an updatable ResultSet 
               // insert column values into the insert row. 
     rs.moveToInsertRow();     // moves cursor to the insert row 
     rs.updateString("TEST_ID", uuid);   // updates the 2nd column 
     rs.updateString("TEST_COMMENT", "Comment for: " + uuid); 
     rs.insertRow(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
     rs.close(); 
     pstmt.close(); 
     conn.close(); 
     } catch (SQLException e) { 
     e.printStackTrace(); 
     } 
    } 
    } 
} 

最初の行は、36文字の長さであるUUID

UUID.randomUUID().toString(); 

を作成します。 ORA-01461エラーが生成され、このサンプル・クラスを実行するが、正常に実行され、データベースに行を挿入する32文字の文字列に生じる

UUID.randomUUID().toString().replaceAll("-", ""); 

に上記行を変更。上記の文字列が保存される "TEST_ID"列はVARCHAR2(40 CHAR)で、32文字と36文字の両方の文字列に対応できます。列の長さをさらに大きな数値に増やしても、何も変更されません。

私のサンプルコードは読んで理解しやすく、この問題の解決方法をお探ししたいと思います。

ありがとう!

データベース情報:

(UUID文字列の長さについて)この問題は、それはそう以上に奇妙であることを示すために同じデータを持つINSERT文を実行するためにわずかに変更さ
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production 
PL/SQL Release 12.1.0.2.0 - Production 
"CORE 12.1.0.2.0 Production" 
TNS for Linux: Version 12.1.0.2.0 - Production 
NLSRTL Version 12.1.0.2.0 - Production 

。次のサンプルコードは、最新のOracleドライバで正常に実行されます。

public static void main(String[] args) { 
    final String uuid = UUID.randomUUID().toString(); 
    ResultSet rs = null; 
    Connection conn = null; 
    PreparedStatement pstmt = null; 
    try { 
     conn = getConnection(); 
     String query = "INSERT INTO TEST_TABLE (TEST_ID, TEST_COMMENT) VALUES (?, ?)"; 
     pstmt = conn.prepareStatement(query); 
     pstmt.setString(1, uuid); // set input values 
     pstmt.setString(2, "Comment for: " + uuid); // set input values 
     rs = pstmt.executeQuery(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
     rs.close(); 
     pstmt.close(); 
     conn.close(); 
     } catch (SQLException e) { 
     e.printStackTrace(); 
     } 
    } 
    } 
+0

こんにちは、私の最初の投稿を編集し、データベース情報を追加しました。ありがとう! – pleft

+0

空文字列ではなく、ハイフン記号を別の文字(たとえば '0'または' a')に置き換えることができますか?問題が本当にサイズかどうかを理解するだけです...どうしますか? –

+0

もちろん、試してみましたが、同じエラーが発生しました。ORA-01461、挿入を行う新しいメイン関数で私の編集をご覧ください。 – pleft

答えて

3

これは12.1.0.2.0 jdbcドライバのバグであり、解決するためにパッチが必要なため、SRをOracleにオープンしました。

+1

今後の参考のため、バグ番号は[Bug 22385253:JDBC 12.1.0.2.0でのRESULTSET.INSERTROWメソッドORA-1461 https://support.oracle.com/epmos/faces/BugDisplay?id=22385253) – gvenzl

+0

@gvenzlありがとうございました! – pleft

-2

このエラーは、(4000バイトが限界である)SQL文で長い4000バイトよりvarchar型の変数を使用しようとして発生します。

uuidには、可能なエンコーディングに注意する必要があります。

とにかくVARCHARデータ型のようなUUIDを格納するのは良い考えではありません。

TEST_IDのデータ型をVARCHAR2からCLOBに変更することができます(下記のコメントのようにPKを削除します)。これは解決策ではありません。

+1

解決策が機能しませんでした。実際に試しましたか? – yannisf

+0

@yannisfいいえ、私は現在モバイルになっていますが、過去には同じ問題がありました。すでにVARBINARY(36)のデータ型を変更しようとしましたか?結果は同じですか? –

+0

@河野佐智:あなたの答えは最も明白ですが、申し訳ありませんが、これは事実ではありません。 uuidは正確に36文字ですが、SQL Developerで同じデータを持つinsert文を実行すると、行はエラーなしで挿入されます。そして私の最初の投稿では、uuidから4文字をトリムすると、サンプルコードが行を正しく挿入することに言及しました。 – pleft

関連する問題