2010-05-18 12 views
26

El código de consulta y consulta:¿No se puede usar una consulta LIKE en un JDBC PreparedStatement?

ps = conn.prepareStatement("select instance_id, ? from eam_measurement where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where resource_group_id = ?) and DSN like '?' order by 2"); 
ps.setString(1,"SUBSTR(DSN,27,16)"); 
ps.setInt(2,defaultWasGroup); 
ps.setString(3,"%Module=jvmRuntimeModule:freeMemory%"); 
rs = ps.executeQuery(); 
while (rs.next()) { bla blah blah blah ... 

Devuelve un vacío ResultSet.

A través de la depuración básica He encontrado su tercer vinculación que el problema es decir

DSN like '?' 

He intentado todo tipo de variaciones, el más sensible de los cuales parecían estar usando:

DSN like concat('%',?,'%') 

pero eso no funciona ya que me falta el ' a cada lado de la cadena concatenada, así que intento:

DSN like ' concat('%',Module=P_STAG_JDBC01:poolSize,'%') ' order by 2 

pero parece que no puedo encontrar una manera de ponerlos en funcionamiento.

¿Qué me estoy perdiendo?

+0

Escribir código Java en un archivo JSP en lugar de en una clase Java real (donde ** debe ** haberlo hecho) y tener problemas con el código Java particular no lo convierte en un problema JSP. Te enfrentarías exactamente al mismo problema al hacerlo en una clase real de Java. Así que eliminé la etiqueta '[jsp]' ya que eso es irrelevante. – BalusC

+1

Es cierto que no es JSP específico, pero no hay nada * incorrecto * con el uso de dicho código en un servlet de acuerdo con la mayoría de los libros que he leído, especialmente cuando es una página de informe super simple de menos de 40 líneas donde la arquitectura de la aplicación es un poco exagerado :) ¡Pero aprecio tu punto! – SeerUK

Respuesta

52

En primer lugar, los marcadores de posición PreparedStatement (esos ? elementos) son para valores de columna solamente, no para nombres de tabla, nombres de columna, funciones/cláusulas SQL, etcétera. Mejor uso String#format() en su lugar. En segundo lugar, debe no citar los marcadores de posición como '?', solo deformaría la consulta final. Los instaladores PreparedStatement ya hacen el trabajo de cotización (y escape) por usted.

Aquí está el SQL fijo:

private static final String SQL = "select instance_id, %s from eam_measurement" 
    + " where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where" 
    + " resource_group_id = ?) and DSN like ? order by 2"); 

Aquí es cómo usarlo:

String sql = String.format(SQL, "SUBSTR(DSN,27,16)"); // This replaces the %s. 
preparedStatement = connection.prepareStatement(sql); 
preparedStatement.setInt(1, defaultWasGroup); 
preparedStatement.setString(2, "%Module=jvmRuntimeModule:freeMemory%"); 

Véase también:

2

Omitir el ' alrededor del ?. Sin el ', ? es un marcador de posición para un parámetro. Con él, es una cadena SQL (es decir, la misma que "?" en Java).

Luego debe concatenar la cadena en el lado de Java; no puede pasar funciones de SQL como parámetros a las consultas; solo valores básicos (como cadena, entero, etc.) porque el controlador JDBC convertirá el parámetro al tipo SQL que la base de datos espera y no puede ejecutar funciones SQL en este paso.

+0

Sin el '' alrededor del? Obtengo un conjunto de resultados vacío también. No es de extrañar que supongo que entonces el sql leería: y DSN como% Module = P_STAG_JDBC01: poolSize% que no le gusta a oráculo y responde con: Falta el parámetro IN o OUT en el índice :: 1 (código de error = 17041) Por lo tanto, necesito agregar los '' s al enlace cuando lo configuré vía ps.setString? – SeerUK

+0

p. Ej. ps.setString (3, "'Module = jvmRuntimeModule: freeMemory'"); Pero también proporciona un conjunto de resultados vacío, como lo hace ps.setString (3, "\ 'Module = jvmRuntimeModule: freeMemory \'"); Aunque java docs dice que no debería ser necesario escapar de un 'inside' 's – SeerUK

+0

@SeerUK: ¡El mensaje de error proviene del parámetro 1, no del parámetro 3! –

10

Hay dos problemas con su extracto. Debes entender cómo funcionan las variables de vinculación. La consulta es no procesada al sustituir los caracteres ? con sus parámetros. En cambio, la declaración se compila con marcadores de posición y luego, durante la ejecución, los valores reales de los parámetros se dan a la base de datos.

En otras palabras, analizar la siguiente consulta:

SELECT instance_id, :p1 
    FROM eam_measurement 
WHERE resource_id IN (SELECT RESOURCE_ID 
         FROM eam_res_grp_res_map 
         WHERE resource_group_id = :p2) 
    AND DSN LIKE '?' 
ORDER BY 2 

Estoy seguro de que el último parámetro se ignorará porque está en una cadena de caracteres delimitada. Incluso si no se ignora, no tiene sentido tener ' caracteres porque Oracle no enlazará un parámetro en una cadena (me sorprende que no haya provocado ningún error, ¿captas excepciones?).

Ahora, si reemplaza su DNS LIKE '?' con DSN LIKE ? y enlaza , esto tendrá sentido y debería devolver las filas correctas.

todavía tiene el problema con su primer parámetro, no va a hacer lo que se espera, es decir, la consulta que se ejecutará será equivalente a la siguiente consulta:

SELECT instance_id, 'SUBSTR(DSN,27,16)' 
    FROM ... 

que no es en absoluto lo mismo que

SELECT instance_id, SUBSTR(DSN,27,16) 
    FROM ... 

que sugeriría el análisis (= prepareStatement) la siguiente consulta si espera que el SUBSTR sea dinámico:

SELECT instance_id, SUBSTR(DSN,?,?) 
    FROM eam_measurement 
WHERE resource_id IN (SELECT RESOURCE_ID 
         FROM eam_res_grp_res_map 
         WHERE resource_group_id = ?) 
    AND DSN LIKE ? 
ORDER BY 2 
0

Usted puede tratar de:

String beforeAndAfter = "%" + yourVariable + "%"; 
11

Si desea utilizar LIKE en declaración preparada y también desea utilizar caracteres% en SIMILARES;

escribir declaración preparada como normalmente ".... como? ...." y si bien la asignación de valor de parámetro a la pregunta uso de marca

ps.setString(1, "%" + "your string value" + "%");

Esto funcionará :)

0

Esto debería trabajo:

"\'" + "?" + "\'" 
0
PreparedStatement ps = con.prepareStatement(
    "select columname from tablename where LOWER(columnname) LIKE LOWER('"+var+"%')"); 

Aquí var es la variable en la que se almacena el valor que se va a buscar ...

+1

Por favor, brinde un poco más de explicación y formatee su código (puede usar "back ticks" o indentar 4 espacios). [Cómo responder] (http://stackoverflow.com/help/how-to-answer) – AgataB

Cuestiones relacionadas