web-dev-qa-db-fra.com

Impossible d'utiliser une requête LIKE dans un état préparé JDBC?

Le code de la requête et la requête:

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

Retourne une ResultSet vide.

Grâce au débogage de base, j’ai trouvé la troisième liaison, c’est-à-dire le problème.

DSN like '?'

J'ai essayé toutes sortes de variations, dont la plus sensée semblait utiliser:

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

mais cela ne fonctionne pas car il me manque le ' de part et d'autre de la chaîne concaténée alors j'essaie:

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

mais je n'arrive tout simplement pas à trouver un moyen de les intégrer qui fonctionne.

Qu'est-ce que je rate?

28
SeerUK

Votre déclaration pose deux problèmes. Vous devez comprendre comment fonctionnent les variables de liaison. La requête est non traitée en substituant les caractères ? par 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 transmises au DB.

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 s'agit d'une chaîne de caractères délimitée. Même s'il n'est pas ignoré, il n'est pas logique d'avoir des caractères ' car Oracle ne liera pas de paramètre dans une chaîne (je suis surpris qu'il n'ait pas généré d'erreur, interceptez-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, car 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 la même chose que 

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

Je suggérerais d'analyser (= prepareStatement) la requête suivante si vous vous attendez à ce que 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
11
Vincent Malgrat

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

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

2
Aaron Digulla
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 ...

0
Saheba

Tu peux essayer:

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