2009-12-09 4 views
1

J'ai quelques problèmes et je suis sûr que c'est quelque chose de stupide.PreparedStatement ne pas retourner ordonné ResultSet

J'ai donc une requête comme

SELECT name, id, xyz FROM table ORDER BY ? 

puis plus tard sur la mise en route du? faire un

ps.setString(1, "xyz"); 

Je publie la requête et la valeur de xyz dans la console. Lorsque je parcours le ResultSet renvoyé à partir de PreparedStatement, les valeurs ne sont pas dans le bon ordre. Ils sont dans l'ordre retourné comme si j'avais laissé la clause ORDER BY désactivée. Lorsque je copie/colle la requête et la valeur dans TOAD, il s'exécute et revient correctement.

Des idées sur pourquoi le ResultSet ne revient pas dans le bon ordre?

Répondre

13

La base de données verra la requête comme

SELECT name, id, xyz FROM table ORDER BY 'xyz' 

C'est-à-dire l'ordre par une expression constante (la chaîne « xyz » dans ce cas). Toute commande satisfera cela.

+0

+1 très bien, Tom. Diable dans les détails – wowest

+0

jeebus, vous pensez que j'aurais pensé à cela. Mais cela l'a éclairci. Merci! – user16208

+0

Vous pouvez uniquement spécifier des constantes dans les instructions préparées. –

5

? est pour les paramètres, vous ne pouvez pas l'utiliser pour insérer des noms de colonnes. Les déclarations générées ressemblera à quelque chose comme

SELECT name, id, xyz FROM table ORDER BY 'xyz' 

afin que vos entrées sont triées par la chaîne « xyz », et non par le contenu de la colonne xyz.

+0

C'est tellement évident maintenant que je le vois, mais j'ai passé de nombreuses heures à essayer de trouver pourquoi mes résultats n'étaient pas triés. Cela résume bien. – styfle

3

Pourquoi pas:

ps.setInteger(1, 3); 

Cordialement.

EDIT: AFAIK Oracle 10g le prend en charge.

0

Les espaces réservés PreparedStatement ne sont pas destinés aux noms de tables ni aux noms de colonnes. Ils sont uniquement destinés aux valeurs de colonne réelles.

Vous pouvez cependant utiliser String#format() pour cela, c'est aussi ce que je fais souvent. Par exemple:

private static final String SQL_SELECT_ORDER = "SELECT name, id, xyz FROM table ORDER BY %s"; 

... 

public List<Data> list(boolean ascending) { 
    String order = ascending ? "ASC" : "DESC"; 
    String sql = String.format(SQL_SELECT_ORDER, order); 
    ... 

Un autre exemple:

private static final String SQL_SELECT_IN = "SELECT name, id, xyz FROM table WHERE id IN (%s)"; 

... 

public List<Data> list(Set<Long> ids) { 
    String placeHolders = generatePlaceHolders(ids.size()); // Should return "?,?,?..." 
    String sql = String.format(SQL_SELECT_IN, placeHolders); 
    ... 
    DAOUtil.setValues(preparedStatement, ids.toArray()); 
    ... 
+1

Cela ne devrait-il pas être "" SELECT nom, id, xyz FROM table ORDER BY% s% s "' et ensuite 'String.format (SQL_SELECT_ORDER, orderby, order); ' – styfle

0

La base de données verra la requête comme celui-ci

SELECT name, id, xyz FROM table ORDER BY 'xyz' 

Je pense que vous devriez ajouter plus variables comme order_field et order_direction

Je suppose que vous avez une méthode comme ci-dessous et je vous donne un exemple pour le résoudre

pulbic List<Object> getAllTableWithOrder(String order_field, String order_direction) { 
    String sql = "select * from table order by ? ?"; 
    //add connection here 

    PreparedStatement ps = (PreparedStatement) conn.prepareStatement(sql); 
    ps.setString(1,order_field); 
    ps.setString(2,order_direction); 

    logger.info(String.valueOf(ps)); //returns something like: [email protected]: select * from table order by 'id' 'desc' 

    String sqlb = String.valueOf(ps); 
    String sqlc = sqlb.replace("'"+order_field+"'", order_field); 
    String sqld = sqlc.replace("'"+order_direction+"'", order_direction); 

    String[] normQuery = sqld.split(":"); 

    ResultSet result = conn.createStatement().executeQuery(normQuery[1]); 

    while(result.next()) { 
     //iteration 
    } 

} 
Questions connexes