2010-05-18 9 views
26

Die Abfrage-Code und Abfrage:Kann keine LIKE-Abfrage in einem JDBC PreparedStatement verwendet werden?

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

Gibt eine leere ResultSet.

Durch grundlegende Debuggen Ich habe seine die dritte binden gefunden, dass das Problem also

ist
DSN like '?' 

ich alle Arten von Variationen versucht haben, die vernünftigste davon verwendet zu werden schien:

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

aber das funktioniert nicht, da ich die ' auf beiden Seiten der verketteten Zeichenfolge fehlt, so versuche ich:

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

aber ich kann einfach nicht einen Weg finden, um sie in das funktioniert zu bekommen.

Was fehlt mir?

+0

Java-Code in eine JSP-Datei schreiben statt in eine echte Java-Klasse (wo Sie ** es getan haben sollten) und Probleme damit haben der bestimmte Java-Code macht es nicht zu einem JSP-Problem. Sie würden in einer echten Java-Klasse genau dem gleichen Problem gegenüberstehen. Also habe ich das '[jsp]' - Tag entfernt, da das irrelevant ist. – BalusC

+1

Wahr ist es nicht JSP spezifisch, aber dann gibt es nichts * falsch * mit der Verwendung solchen Codes in einem Servlet nach den meisten Büchern, die ich gelesen habe, besonders wenn es eine super einfache Berichtsseite von weniger als 40 Zeilen Code ist, wo Anwendungsarchitektur ist ein wenig Overkill :) Aber ich schätze Ihren Standpunkt! – SeerUK

Antwort

52

Zuerst sind die PreparedStatement Platzhalter (diese ? Dinge) für Spaltenwerte nur, nicht für Tabellennamen, Spaltennamen, SQL-Funktionen/Klauseln, usw. Besser verwenden Sie stattdessen String#format(). Zweitens sollten Sie nicht die Platzhalter wie '?' zitieren, würde es nur die letzte Abfrage falsch machen. Die PreparedStatement Setter erledigen bereits den Quotierungs- (und Escape-) Job für Sie.

Hier ist der festen SQL:

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

Hier ist, wie es zu benutzen:

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

Siehe auch:

2

Auslassen der ' um die ?. Ohne ' ist ? ein Platzhalter für einen Parameter. Damit ist es eine SQL-Zeichenfolge (d. H. Das gleiche wie "?" in Java).

Dann müssen Sie die Zeichenfolge auf der Java-Seite verketten; Sie können keine SQL-Funktionen als Parameter an Abfragen übergeben. nur Basiswerte (wie String, Integer usw.), da der JDBC-Treiber den Parameter in den von der Datenbank erwarteten SQL-Typ konvertiert und in diesem Schritt keine SQL-Funktionen ausführen kann.

+0

Ohne die '' um die? Ich bekomme auch ein leeres resultSet. Nicht überraschend, ich denke, dann würde die SQL lesen: und DSN wie% Module = P_STAG_JDBC01: poolSize%, die oracle nicht gefällt und antwortet mit: Fehlender IN oder OUT Parameter bei Index :: 1 (Fehlercode = 17041) Also muss ich füge die 's zur Bindung hinzu, wenn ich es über ps.setString setze? – SeerUK

+0

z.B. ps.setString (3, "'Modul = jvmRuntimeModule: freeMemory'"); Aber gibt auch eine leere Ergebnismenge, wie ps.setString (3, "\ 'Module = jvmRuntimeModule: freeMemory \'"); Obwohl java docs sagt, dass es nicht notwendig sein sollte, ein "inside" zu entkommen s – SeerUK

+0

@SeerUK: Die Fehlermeldung kommt von Parameter 1, nicht von Parameter 3! –

10

Es gibt zwei Probleme mit Ihrer Aussage. Sie müssen verstehen, wie Bind-Variablen funktionieren. Die Abfrage wird nicht durch Substituieren der Zeichen ? mit Ihren Parametern verarbeitet. Stattdessen wird die Anweisung mit Platzhaltern kompiliert, und während der Ausführung werden die tatsächlichen Werte der Parameter dem DB übergeben.

Mit anderen Worten, analysieren Sie die folgende Abfrage:

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 

Ich bin ziemlich sicher, der letzte Parameter wird ignoriert, weil es in einem begrenzten Zeichenfolge ist. Auch wenn es nicht ignoriert wird, macht es keinen Sinn, ' Zeichen herum zu haben, weil Oracle einen Parameter in einer Zeichenfolge nicht bindet (ich bin überrascht, dass es keinen Fehler ausgelöst hat, fangen Sie Ausnahmen?).

Jetzt, wenn Sie Ihre durch DSN LIKE ? ersetzen und binden "%Module=jvmRuntimeModule:freeMemory%" wird dies Sinn machen und sollte die richtigen Zeilen zurückgeben.

Sie immer noch das Problem mit dem ersten Parameter haben, wird es nicht tun, was Sie erwarten, dh die Abfrage, die auf die folgende Abfrage gleichwertig ausgeführt werden wird:

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

, die überhaupt nicht ist die gleichen wie

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

würde ich vorschlagen, das Parsen (= prepareStatement) die folgende Abfrage, ob Sie die SUBSTR dynamisch sein erwarten:

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

können Sie versuchen:

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

Wenn Sie LIKE in vorbereitete Anweisung verwenden und wollen auch% Zeichen in LIKE verwenden;

schreiben vorbereitete Erklärung, wie sie normalerweise ".... wie? ....", und während die Zuordnung Parameterwert Zeichen Verwendung

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

Diese Arbeit wird in Frage :)

0

Dies sollte Arbeit:

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

Hier var ist die Variable, in der der zu suchende Wert gespeichert wird ...

+1

Bitte geben Sie ein bisschen mehr Erklärung und formatieren Sie Ihren Code (Sie können "Back Ticks" verwenden oder 4 Leerzeichen einrücken). [Wie zu antworten] (http://stackoverflow.com/help/how-to-answer) – AgataB

Verwandte Themen