2009-03-02 6 views
7

Tengo una consulta que tieneOracle10 y JDBC: ¿cómo hacer que CHAR ignore los espacios finales en la comparación?

... DONDE PRT_STATUS = 'ONT' ...

El campo prt_status se define como CHAR (5) sin embargo. Por lo tanto, siempre está lleno de espacios. La consulta no coincide con nada como resultado. Para hacer este trabajo de consulta que tengo que hacer

... DONDE rtrim (PRT_STATUS) = 'ONT'

el que hace el trabajo.

Eso es molesto.

Al mismo tiempo, un par de clientes DBMS puros -java (Oracle SQLDeveloper y AquaStudio) NO tengo un problema con la primera consulta, devuelven el resultado correcto. TOAD tampoco tiene problema.

Supongo que simplemente ponen la conexión en algún modo de compatibilidad (por ejemplo, ANSI), por lo que el Oracle sabe que CHAR (5) espera que se compare con respecto a los caracteres finales.

¿Cómo puedo hacerlo con los objetos de conexión que obtengo en mi aplicación?

ACTUALIZACIÓN No puedo cambiar el esquema de la base de datos.

SOLUCIÓN De hecho, Oracle comparó los campos con los parámetros pasados.

Cuando se realiza el enlace, la cadena se pasa a través de PreparedStatement.setString(), que establece el tipo a VARCHAR y, por lo tanto, Oracle utiliza la comparación sin relleno, y falla.

Intenté usar setObject (n, str, Types.CHAR). Falla La descompilación muestra que Oracle ignora CHAR y lo pasa nuevamente como VARCHAR.

La variante que finalmente funciona es

setObject(n,str,OracleTypes.FIXED_CHAR); 

Esto hace que el código no es portátil sin embargo.

Los clientes de IU tienen éxito por una razón diferente: usan literales de caracteres, no son vinculantes. Cuando escribo PRT_STATUS = 'ONT', 'ONT' es un literal, y como tal, comparo el uso de la forma acolchada.

Respuesta

8

Tenga en cuenta que Oracle compares CHAR values using blank-padded comparison semantics.

De Datatype Comparison Rules,

Oracle utiliza la comparación rellenada con blancos semántica sólo cuando ambos valores en la comparación son o bien expresiones de CHAR tipo de datos, NCHAR, los literales de texto, o valores devueltos por la función USER .

En su ejemplo, ¿está 'ONT' pasado como un parámetro de vinculación, o está incorporado en la consulta textualmente, como lo ilustra? Si es un parámetro de vinculación, asegúrese de que esté enlazado como tipo CHAR. De lo contrario, verifique la versión de la biblioteca cliente utilizada, ya que las versiones realmente antiguas de Oracle (por ejemplo, v6) tendrán una semántica de comparación diferente para CHAR.

+0

Eso está bien. Ver mi respuesta actualizada entonces. – vladr

+0

Hmm ... eso tiene sentido. SetString de JDBC utiliza VARCHAR para enlazar un parámetro de cadena. No estoy seguro si puedo usar esto para resolver el problema, pero al menos se vuelve más claro ahora. –

+0

Probablemente, a la derecha: "Oracle usa una semántica de comparación no almohadillada siempre que uno o ambos valores en la comparación tengan el tipo de datos VARCHAR2 o NVARCHAR2". Necesito hacer una prueba para verificarlo. –

0

Cambiaría la columna CHAR (5) en varchar2 (5) en db.

+0

fuera de cuestión. DB no pertenece a nuestro grupo. –

1

Si no puede cambiar su tabla de base de datos, puede modificar su consulta.

Algunas alternativas para RTRIM:

.. DONDE PRT_STATUS como 'ONT%' ...

.. DONDE PRT_STATUS = 'ONT' ... - 2 espacios en blanco detrás de T

.. DONDE PRT_STATUS = RPAD ('ONT', 5' ') ...

0

puede utilizar yeso para la operación carbón en su consulta:

... WHERE PRT_STATUS=cast('ONT' as char(5)) 

O en forma más genérica JDBC:

... WHERE PRT_STATUS=cast(? as char(5)) 

Y luego, en su código JDBC no utilizar statement.setString(1, "ONT");

Cuestiones relacionadas