2016-01-07 8 views
13

Ich habe ein seltsames Problem beim Versuch, eine Auswahl für Update-Anweisung auszuführen und anschließend eine Einfügung oder ein Update auszuführen. Ich bekomme eine ORA-01461 Ausnahme. Dies geschieht nur bei Verwendung des neuesten ojdbc-Treibers (12.1.0.2), während es in der älteren Version einwandfrei funktioniert (12.1.0.1).PreparedStatement + Wählen Sie für Update + Oracle 12c + ORA-01461 in Primärschlüssel Spalte

Genauer gesagt scheint der neueste Treiber eine Art Grenze in der Länge des Primärschlüssels zu haben (begrenzt auf 32 Zeichen), obwohl die entsprechende Spalte mehr als 32 Zeichen enthält. Beispielcode das Problem ist folgendes zu replizieren:

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") 
); 

und einige 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(); 
     } 
    } 
    } 
} 

Erste Zeile des Haupt-Methode erstellt eine UUID

UUID.randomUUID().toString(); 

die 36 Zeichen lang ist. Das Ausführen dieses Beispielklasse wird ein ORA-01461-Fehler erzeugen, aber die Änderung der Linie oben genannten

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

die bis zu 32 Zeichen-String ergibt wird die Zeile in der Datenbank korrekt und Einfügen ausgeführt. Beachten Sie, dass die Spalte "TEST_ID", in der die obige Zeichenfolge gespeichert wird, VARCHAR2 (40 CHAR) ist und 32 Zeichenfolgen und 36 Zeichenfolgen aufnehmen kann. Eine Erhöhung der Spaltenlänge auf noch größere Zahlen ändert nichts.

Ich hoffe, dass mein Beispielcode leicht zu lesen und zu verstehen ist und ich freue mich auf eine Lösung/Erklärung für dieses Problem.

Danke!

Datenbank Info:

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 

Modified leicht eine Insert-Anweisung mit den gleichen Daten laufen um zu zeigen, dass dieses Problem mehr komisch ist, als es scheint (in Bezug auf die UUID String-Länge). Der folgende Beispielcode ausführt korrekt mit den neuesten Oracle-Treiber:

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

Hallo, habe meinen ersten Beitrag bearbeitet und Datenbankinformationen hinzugefügt. Vielen Dank! – pleft

+0

Können Sie versuchen, das Bindestrichsymbol durch ein anderes Zeichen (z. B. "0" oder "a") anstelle einer leeren Zeichenfolge zu ersetzen? Nur um zu verstehen, ob das Problem wirklich die Größe ist ... Was passiert? –

+0

Sicher, nur versucht es, der gleiche Fehler tritt auf ORA-01461, siehe meine Bearbeitung mit der neuen Hauptfunktion, die eine Einfügung tut. – pleft

Antwort

3

Eröffnet eine SR zu Oracle, da dies ein Fehler von 12.1.0.2.0 jdbc Treiber ist und würde einen Patch benötigen, um es zu lösen.

+1

Nur für zukünftige Referenz lautet die Fehlernummer [Bug 22385253: RESULTATEET.INSERTROW METHOD MIT JDBC 12.1.0.2.0 THROWS ORA-1461] (https://support.oracle.com/epmos/faces/BugDisplay?id=22385253) – gvenzl

+0

@gvenzl ja danke für das notieren! – pleft

-2

Dieser Fehler mehr auftritt versucht, eine VARCHAR Variable zu verwenden, als 4000 Bytes in einer SQL-Anweisung (4000 Bytes sind die Grenze).

Sie sollten überprüfen, was die uuid Variable enthält, achten Sie auf mögliche Codierung.

Wie auch immer speichern Sie die UUID wie VARCHAR-Datentyp ist keine gute Idee.

Die Abhilfe, damit es funktioniert die TEST_ID Datentyp VARCHAR2-CLOB ändern werden (Entfernen der PK wie Sie im Kommentar unten gesagt), aber dies ist nicht die Lösung.

+1

Ihre Lösung hat nicht funktioniert. Hast du es tatsächlich versucht? – yannisf

+0

@yannisf Nein, da ich jetzt auf dem Handy bin, aber in der Vergangenheit habe ich das gleiche Problem. Haben Sie bereits versucht, den Datentyp in 'VARBINARY (36)' zu ändern? Ist das Ergebnis dasselbe? –

+0

@Satoshi Kouno: Ihre Antwort ist die offensichtlichste, aber tut mir leid, das ist nicht der Fall. Uuid ist genau 36 Zeichen lang, wenn Sie eine Insert-Anweisung mit denselben Daten in SQL Developer ausführen, wird die Zeile ohne Fehler eingefügt. Und in meinem ersten Beitrag erwähne ich, dass wenn Sie 4 Zeichen aus der UUID trimmen, fügt der Beispielcode die Zeile korrekt ein. – pleft