JDBC de Oracle conjunto de caracteres y 4000 char límite

Estamos tratando de almacenar una codificación UTF-16 en una Cadena de AL32UTF8 base de datos de Oracle.

Nuestro programa funciona perfectamente en una base de datos que utiliza WE8MSWIN1252 como charset. Cuando tratamos de ejecutar en una base de datos que utiliza AL32UTF8 se llega a un java.sql.SQLException: ORA-01461: can bind a LONG value only for insert into a LONG column.

En el testcase a continuación todo funciona bien, siempre y cuando los datos de entrada no es excesivamente largo.

La Cadena de entrada puede superar los 4.000 caracteres. Queremos retener tanta información como sea posible, aunque nos damos cuenta de que la entrada tendrá que ser cortado.

Nuestra base de datos de las tablas se definen utilizando la CHAR palabra clave (ver más abajo). Teníamos la esperanza de que esto nos va a permitir almacenar hasta 4000 caracteres de cualquier conjunto de caracteres. Se puede hacer esto? Si es así, ¿cómo?

Hemos tratado de convertir la Cadena a UTF8 el uso de un ByteBuffer sin éxito. OraclePreparedStatement.setFormOfUse(...) también no nos ayude.

De cambiar a un CLOB no es una opción. Si la cadena es demasiado larga debe ser cortado.

Este es nuestro código en el momento:

public static void main(String[] args) throws Exception {
    String ip ="193.53.40.229";
    int port = 1521;
    String sid = "ora11";
    String username = "obasi";
    String password = "********";

    String driver = "oracle.jdbc.driver.OracleDriver";
    String url = "jdbc:oracle:thin:@" + ip + ":" + port + ":" + sid;
    Class.forName(driver);

    String shortData = "";
    String longData = "";
    String data;

    for (int i = 0; i < 5; i++)
        shortData += "é";

    for (int i = 0; i < 4000; i++)
        longData += "é";

    Connection conn = DriverManager.getConnection(url, username, password);

    PreparedStatement stat = null;
    try  {
        stat = conn.prepareStatement("insert into test_table_short values (?)");
        data = shortData.substring(0, Math.min(5, shortData.length()));
        stat.setString(1, data);
        stat.execute();

        stat = conn.prepareStatement("insert into test_table_long values (?)");
        data = longData.substring(0, Math.min(4000, longData.length()));
        stat.setString(1, data);
        stat.execute();
    } finally {
        try {
            stat.close();
        } catch (Exception ex){}
    }
}

Este es el script de creación de la tabla sencilla:

CREATE TABLE test_table_short (
    DATA    VARCHAR2(5 CHAR);
);

CREATE TABLE test_table_long (
    DATA    VARCHAR2(4000 CHAR);
);

El caso de prueba funciona perfectamente en el corto de datos. En el largo de datos, sin embargo se mantiene el error. Incluso cuando nuestros longData es sólo 3000 caracteres de largo, todavía no se ejecute correctamente.

Gracias de antemano!

OriginalEl autor Arolition | 2012-07-19

2 Kommentare

  1. 9

    Antes de Oracle 12.1, un VARCHAR2 columna se limita a almacenar 4000 bytes de datos en la base de datos de conjunto de caracteres, incluso si se declara la VARCHAR2(4000 CHAR). Ya que cada carácter en la cadena requiere 2 bytes de almacenamiento en el formato UTF-8 conjunto de caracteres, usted no será capaz de almacenar más de 2000 caracteres en la columna. Por supuesto, ese número va a cambiar si algunos de tus personajes realmente requieren sólo 1 byte de almacenamiento, o si algunos de ellos requieren más de 2 bytes de almacenamiento. Cuando la base de datos es el conjunto de caracteres de Windows-1252, cada carácter en la cadena que requiere de un solo byte de almacenamiento, de modo que usted será capaz de almacenar 4000 caracteres en la columna.

    Ya que tienen cadenas más largas, sería posible declarar la columna como un CLOB en lugar de como un VARCHAR2? Que (efectivamente) quitar la limitación de la longitud (hay un límite en el tamaño de un CLOB que depende de la versión de Oracle y el tamaño de bloque, pero al menos en las múltiples GB de rango).

    Si usted sucede estar en el uso de Oracle 12.1 o más tarde, el max_string_size parámetro permite aumentar el tamaño máximo de un VARCHAR2 en la columna de 4000 bytes a 32767 bytes.

    Gracias por tu respuesta. Tristemente, en este caso, el uso de clob es fuera de la cuestión para nosotros. De acuerdo a la enlace esta es la respuesta correcta. Sin embargo, link es bastante engañoso, en mi humilde opinión. Sabes donde esta se explica en la documentación? Hemos estado buscando mucho, pero no podía encontrar esto.
    He añadido un comentario a MODO de hilo. La respuesta es correcta en la medida en que va. Sólo que no se tenga en cuenta que si un particular 4000 caracteres requiere más de 4000 bytes de almacenamiento que la 4000 bytes límite de capacidad todavía de patadas en el.
    UTF-8 es una variable de codificación de longitud. Muchos de los caracteres asiáticos requieren por lo menos tres bytes para codificar.

    OriginalEl autor Justin Cave

  2. 4

    Resuelto este problema mediante el corte de la Cadena para la requieren byte de longitud. Tenga en cuenta que esto no puede hacerse simplemente utilizando

    stat.substring(0, length)

    ya que produce una Cadena UTF-8 que puede ser hasta tres veces más de lo permitido.

    while (stat.getBytes("UTF8").length > length) {
      stat = stat.substring(0, stat.length()-1);
    }

    nota no utilice stat.getBytes (), ya que esto depende de que el conjunto ‘archivo.codificación’ y produce Windows-1252 o bytes UTF-8!

    Si utiliza Hibernate usted puede hacer esto utilizando org.hibernate.Interceptor!

    OriginalEl autor dfreis

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea