2010-05-18 3 views
26

Le code de requête et requête:Impossible d'utiliser une requête LIKE dans un PreparedStatement JDBC?

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

Renvoie un ResultSet vide.

Grâce débogage de base que j'ai trouvé son troisième bind qui est le problème à savoir

DSN like '?' 

J'ai essayé toutes sortes de variations, dont le plus sensible semblait utiliser:

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

mais cela ne fonctionne pas comme je manque le ' de chaque côté de la chaîne concaténée donc j'essayer:

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

mais je n'arrive pas à trouver un moyen de les faire fonctionner.

Qu'est-ce qui me manque?

+0

Ecriture de code Java dans un fichier JSP plutôt que dans une classe Java réelle (où ** ** l'aurait fait) et avoir des problèmes avec le code Java particulier n'en fait pas un problème JSP. Vous seriez confronté exactement au même problème si vous le faites dans une classe Java réelle. J'ai donc enlevé la balise '[jsp]' car c'est sans importance. – BalusC

+1

Vrai, ce n'est pas spécifique à JSP, mais il n'y a rien de mal * à utiliser un tel code dans une servlet selon la plupart des livres que j'ai lus, surtout quand il s'agit d'une page de rapport de 40 lignes est un peu exagéré :) Mais j'apprécie votre point! – SeerUK

Répondre

52

D'abord, les PreparedStatement (ces espaces réservés ? choses) sont pour colonne valeurs, et non pour les noms de table, les noms de colonnes, des fonctions SQL/clauses, etcetera. Mieux vaut utiliser String#format() à la place. Deuxièmement, vous devez pas citer les espaces réservés comme '?', il ne serait que malformer la requête finale. Les setters PreparedStatement font déjà le job de devis (et d'échappement) pour vous.

est ici fixe 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"); 

Voici comment l'utiliser:

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

Voir aussi:

2

Omettez le ' autour du ?. Sans le ', ? est un espace réservé pour un paramètre. Avec lui, c'est une chaîne SQL (c'est-à-dire identique à "?" en Java).

Ensuite, vous devez concaténer la chaîne du côté Java; vous ne pouvez pas passer des fonctions SQL en tant que paramètres aux requêtes; Seules les valeurs de base (telles que string, integer, etc.) car le pilote JDBC convertira le paramètre en type SQL attendu par la base de données et ne pourra pas exécuter les fonctions SQL à cette étape.

+0

Sans le '' autour du? Je reçois un résultat vide aussi. Sans surprise je suppose que le sql lirait alors: et DSN comme% Module = P_STAG_JDBC01: poolSize% qui oracle n'aime pas et répond avec: Paramètre IN ou OUT manquant à l'index :: 1 (code d'erreur = 17041) Ainsi je dois ajouter les '' s à la liaison quand je l'ai défini via ps.setString? – SeerUK

+0

par exemple. ps.setString (3, "'Module = jvmRuntimeModule: freeMemory'"); Mais donne également un ensemble de résultats vide, comme le fait ps.setString (3, "\ 'Module = jvmRuntimeModule: freeMemory \'"); Bien que java docs dise qu'il ne devrait pas être nécessaire d'échapper un «inside» "s – SeerUK

+0

@SeerUK: Le message d'erreur provient du paramètre 1, pas du paramètre 3! –

10

Votre relevé comporte deux problèmes. Vous devez comprendre comment fonctionnent les variables de liaison. La requête est non traitée en substituant les caractères ? avec vos paramètres. Au lieu de cela, l'instruction est compilée avec des espaces réservés puis, lors de l'exécution, les valeurs réelles des paramètres sont données à la base de données.

En d'autres termes, vous analysez la requête suivante:

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 

Je suis sûr que le dernier paramètre sera ignoré car il est dans une chaîne de caractères délimitée. Même s'il n'est pas ignoré, cela n'a aucun sens d'avoir des caractères autour de ' parce qu'Oracle ne liera pas un paramètre dans une chaîne (je suis surpris qu'il n'ait pas soulevé d'erreur, attrapez-vous des exceptions?). Maintenant, si vous remplacez votre DNS LIKE '?' par DSN LIKE ? et que vous liez "%Module=jvmRuntimeModule:freeMemory%" cela aura du sens et devrait renvoyer les lignes correctes.

Vous avez toujours le problème avec votre premier paramètre, il ne fera pas ce que vous attendez, à savoir la requête qui sera exécutée sera équivalente à la requête suivante:

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

qui n'est pas du tout le même que

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

je suggère l'analyse syntaxique (= prepareStatement) la requête suivante si vous attendez la SUBSTR soit dynamique:

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

Vous pouvez essayer:

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

Si vous souhaitez utiliser LIKE dans instruction préparée et que vous voulez aussi utiliser des caractères% dans SIMILAIRES;

écrire déclaration préparée comme normalement ".... comme? ...." et tout en attribuant la valeur de paramètre à point d'interrogation utilisation

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

Cela fonctionne :)

0

Cela devrait travail:

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

ici var est la variable dans laquelle la valeur à rechercher est stockée ...

+1

Veuillez donner un peu plus d'explications et formater votre code (vous pouvez utiliser "back ticks" ou indenter 4 espaces). [Comment répondre] (http://stackoverflow.com/help/how-to-answer) – AgataB

Questions connexes