programing

Prepared Statement + 업데이트를 위해 선택 + 기본 키 열에 Oracle 12c + ORA-01461

bestprogram 2023. 7. 26. 22:15

Prepared Statement + 업데이트를 위해 선택 + 기본 키 열에 Oracle 12c + ORA-01461

업데이트를 위해 선택 문을 실행한 다음 삽입 또는 업데이트를 실행하려고 할 때 이상한 문제가 발생합니다.ORA-01461 예외가 발생했습니다.이 문제는 최신 ojdbc 드라이버(12.1.0.2)를 사용하는 경우에만 발생하며 이전 드라이버(12.1.0.1)에서는 정상적으로 작동합니다.

보다 구체적으로 최신 드라이버는 해당 열이 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();
      }
    }
  }
}

주 메서드의 첫 번째 줄에 UUID 생성

 UUID.randomUUID().toString();

36자 길이입니다.이 샘플 클래스를 실행하면 ORA-01461 오류가 발생하지만 위에서 언급한 라인을 다음으로 변경합니다.

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

32자 문자열이 올바르게 실행되고 행이 데이터베이스에 삽입됩니다.위 문자열이 저장된 "TEST_ID" 열은 VARCHAR2(40CHAR)이며 32 및 36자 문자열을 모두 수용할 수 있습니다.열의 길이를 더 큰 숫자로 늘린다고 해서 변경되는 것은 없습니다.

제 샘플 코드가 읽기 쉽고 이해하기 쉬웠으면 좋겠고 이 문제에 대한 해결책/설명을 기대하고 있습니다.

감사합니다!

데이터베이스 정보:

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

(UUID 문자열 길이와 관련하여) 이 문제가 보이는 것보다 더 이상하다는 것을 나타내기 위해 동일한 데이터로 삽입 문을 실행하도록 약간 수정되었습니다.다음 샘플 코드는 최신 오라클 드라이버로 올바르게 실행됩니다.

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

이는 12.1.0.2.0 jdbc 드라이버의 버그이며 이를 해결하기 위해 패치가 필요하기 때문에 Oracle에 SR을 열었습니다.

이 오류는 SQL 문에서 4000바이트보다 긴 varchar 변수를 사용하려고 시도할 때 발생합니다(4000바이트가 제한됨).

당신은 그것이 무엇인지 확인해야 합니다.uuid변수에는 가능한 인코딩에 주의를 기울이는 내용이 포함되어 있습니다.

어쨌든 VARCHAR 데이터 유형과 같은 UUID를 저장하는 것은 좋은 생각이 아닙니다.

이 작업을 수행하기 위한 해결 방법은 다음과 같습니다.TEST_ID데이터 형식VARCHAR2로.CLOB(아래 댓글에서 말씀하신 것처럼 PK 제거) 하지만 이것은 해결책이 아닙니다.

언급URL : https://stackoverflow.com/questions/34655888/preparedstatement-select-for-update-oracle-12c-ora-01461-in-primary-key-co