domingo, 13 de mayo de 2007

ORA-01461: can bind a LONG value only for insert into a LONG column

Este error puede ocurrir cuando se insertan o actualizan valores en la base de datos desde alguna aplicación cliente, como por ejemplo Forms o Java.

En mi caso utilizando Forms 10g, intentaba grabar en un textbox dos mil y tantos caracteres en un formulario, obteniendo repetidamente el error. El campo de formulario estaba definido como CHAR de largo máximo 4000 y la columna de la base de datos era VARCHAR2 de 4000; entonces donde estaba el problema?

El problema resultó en el character set de la base de datos y el character set del cliente.
La base de datos tenía un character set multibyte, es decir que puede utilizar varios bytes para representar un caracter. El cliente (en mi caso Application Server 10g), estaba configurado con un character set single byte. Resultado: el cliente enviaba 1 byte y la base de datos almacenaba en 3 bytes. Al enviar más de la tercera parte del tamaño de la columna, se produce un bug (conocido) de Oracle en el cual supone que se le está enviando un LONG. Forms internamente utiliza bind variables para las operaciones en formularios, por lo tanto se produce el error: can bind a LONG value only for insert into a LONG column.

La solución simple es modificar el character set del cliente, en este caso del Application Server. Particularmete elegí el mismo que tenía la base de datos (UTF8).

Los datos quedan intactos, y el cambio en mi cliente es transparente. Ahora cliente y servidor tienen los mismos juegos de caracteres, y evita que se produzcan las conversiones que llevan al bug mencionado.

Para conocer el character set de la base de datos, puede ejecutarse esta consulta desde SQL*Plus:

SELECT VALUE FROM v$nls_parameters WHERE PARAMETER = 'NLS_CHARACTERSET';

6 comentarios:

JC "Joanqui" Fuentes dijo...

Muy util tu aclaración, buscaba un problema de longitudes de cadena y era realmente un error en el charset del cliente y el de la base de datos, que quedó mal tras instalar la última versión de Oracle

jmgoyesc dijo...

Es muy buena la aclaración. Sin embargo al igual el char set en la BD y la aplicación los caracteres como tildes y eñes se dañan en la aplicación. No se si conoce una forma de escaparlos en la forma o de solucionar el problema de otra manera. Gracias

neocygnus dijo...

Disculpame; pero entendi todo menos la parte facil; como haces para configurar el character set en el application server? gracias

jmgoyesc dijo...

Para cambiar el character set del OAS o DevSuite (Segun sea el caso) se debe modificar el archivo default.env y agregar la linea NLS_LANG=MEXICAN SPANISH_MEXICO.AL32UTF8. Y reiniciar. Como recomendación de mi investgacion es recomendable compilar las formas en el mismo encoding en el que se van a usar.

kAlvaro dijo...

Desconozco si evita el ORA-01461 pero si cambiamos el juego de caracteres del cliente para ajustarlo al del servidor la aplicación recibirá datos en un charset que no sabrá manejar correctamente. Es peor el remedio que la enfermedad.

lfer dijo...

Alvaro,
No se a que te refieres exactamente. Es un tema de 'entendimiento' entre cliente Oracle y servidor Oracle. Si cliente y servidor tienen el mismo juego, entonces no habra conversiones.
No se que tipo de aplicacion tienes, pero en el caso de Forms (como el del ejemplo) no hay problemas.