Non è ansible utilizzare una query LIKE in un PreparedStatement JDBC?

Il codice di query e la query:

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 ... 

Restituisce un ResultSet vuoto.

Attraverso il debug di base ho trovato il terzo problema, ovvero il problema

 DSN like '?' 

Ho provato tutti i tipi di variazioni, le più sensate delle quali sembravano usare:

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

ma quello non funziona siccome mi manca il ' su entrambi i lati della stringa concatenata così provo:

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

ma proprio non riesco a trovare un modo per farli funzionare in quel modo.

Cosa mi manca?

Innanzitutto, i segnaposto PreparedStatement (quelle ? Cose) sono solo per valori di colonna , non per nomi di tabelle, nomi di colonne, funzioni / clausole SQL, eccetera. Meglio usare String#format() invece. Secondo, non dovresti citare i segnaposto come '?' , sarebbe solo malformare la query finale. I settatori PreparedStatement già fanno il lavoro di quotazione (e di fuga) per te.

Ecco l’SQL fisso:

 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"); 

Ecco come 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%"); 

Vedi anche :

  • Esercitazione su Sun JDBC: utilizzo di istruzioni preparate
  • Formatta la syntax della stringa

Ci sono due problemi con la tua affermazione. Devi capire come funzionano le variabili di bind. La query non viene elaborata sostituendo i caratteri ? con i tuoi parametri. Invece, l’istruzione viene compilata con i segnaposto e quindi, durante l’esecuzione, i valori effettivi dei parametri vengono assegnati al DB.

In altre parole, si analizza la seguente query:

 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 

Sono abbastanza sicuro che l’ultimo parametro verrà ignorato perché si trova in una stringa di caratteri delimitata. Anche se non è ignorato, non ha senso avere ' caratteri in giro perché Oracle non vincolerà un parametro in una stringa (sono sorpreso che non abbia generato alcun errore, rilevi eccezioni?).

Ora se sostituisci il tuo DNS LIKE '?' con DSN LIKE ? e associa "%Module=jvmRuntimeModule:freeMemory%" questo avrà senso e dovrebbe restituire le righe corrette.

Hai ancora il problema con il tuo primo parametro, non farà quello che ti aspetti, cioè la query che verrà eseguita sarà equivalente alla seguente query:

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

che non è affatto uguale a

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

Vorrei suggerire l’analisi (= prepareStatement) della seguente query se ti aspetti che il SUBSTR sia dinamico:

 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 

Se si desidera utilizzare LIKE nell’istruzione preparata e si desidera anche utilizzare% caratteri in LIKE;

scrivere la dichiarazione preparata come normalmente “…. LIKE? ….” e mentre si assegna il valore del parametro all’uso del punto interrogativo

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

Funzionerà 🙂

Ometti l ' intorno ? . Senza il ' , ? è un segnaposto per un parametro. Con esso, è una stringa SQL (cioè uguale a "?" In Java).

Quindi è necessario concatenare la stringa sul lato Java; non è ansible passare le funzioni SQL come parametri alle query; solo valori di base (come stringa, numero intero, ecc.) poiché il driver JDBC convertirà il parametro nel tipo SQL previsto dal database e non può eseguire le funzioni SQL in questo passaggio.

Puoi provare:

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

Questo dovrebbe funzionare:

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

Qui var è la variabile in cui viene memorizzato il valore da cercare …