2009-07-30 3 views
22

J'essaie d'utiliser des instructions préparées pour définir un nom de table pour sélectionner des données, mais je continue d'obtenir une erreur lorsque j'exécute la requête.Utilisation des instructions Prepared pour définir le nom de la table

L'erreur et l'exemple de code sont affichés ci-dessous.

[Microsoft][ODBC Microsoft Access Driver] Parameter 'Pa_RaM000' specified where a table name is required. 



private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [?]"; //?=date 
public Execute(String reportDate){ 
    try { 

     Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); 
     Connection conn = DriverManager.getConnection(Display.DB_MERC); 
     PreparedStatement st = conn.prepareStatement(query1); 
     st.setString(1, reportDate); 
     ResultSet rs = st.executeQuery(); 

Des idées sur ce qui pourrait être à l'origine de cela?

+0

Oui, désinfection des entrées pour éviter les injections SQL! –

+1

Si vous avez besoin de substituer différents noms de tables dans une requête avec la même structure, cela indique une faille dans la conception de votre base de données. Au moins, il pointe vers plusieurs tables avec les mêmes attributs de relation. Normaliser dans une seule table avec une colonne "sujet". –

Répondre

29

Un nom de table ne peut pas être utilisé en tant que paramètre. Ça doit être codé en dur. Ainsi, vous pouvez faire quelque chose comme:

private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [" + reportDate + "?]"; 
+0

Ok merci, devinez malade juste utiliser un remplacement de chaîne A accepté votre réponse comme réponse Merci! – Brandon

+4

Ne pas! C'est un problème de sécurité dû à l'injection SQL. – Benvorth

+7

utilisez 'org.apache.commons.lang.StringEscapeUtils.escapeSql' sur le nom de la table pour vous assurer que vous ne mettez pas votre schéma en danger. – Sebas

-2

Je ne suis pas sûr que vous pouvez utiliser un PreparedStatement pour spécifier le nom de la table, juste la valeur de certains champs. Quoi qu'il en soit, vous pouvez essayer la même requête mais, sans les crochets:

"SELECT plantID, edrman, plant, vaxnode FROM ?" 
+0

Vous avez besoin de parenthèses pour échapper "/" dans les requêtes ... ou il peut s'agir de dates. Je l'ai regardé l'été dernier – Brandon

-2
String table="pass"; 

String st="select * from " + table + " "; 

PreparedStatement ps=con.prepareStatement(st); 

ResultSet rs = ps.executeQuery(); 
+1

Pouvez-vous donner un peu de contexte à votre réponse, de cette façon les futurs lecteurs peuvent apprendre à l'appliquer à leurs problèmes et pas seulement dans cette situation. – Newd

+4

Vulnérable à l'injection SQL. Ne faites pas cela! –

-3

Il est un moyen de transmettre le nom de la table comme une variable

chaîne NameOfTable = "test.Employee"; Chaîne Fquery = "SELECT * FROM" + NameOfTable + "où Done = 'No'"

Note: il devrait y avoir un espace entre FROM et la réussite « et aussi entre » et où mot-clé

+4

Vulnérable à l'injection SQL. Absolument PAS une réponse! –

0

Comme un certain nombre de gens ont dit, vous ne pouvez pas utiliser un paramètre de déclaration pour un nom de table, uniquement pour les variables faisant partie de la condition. En fonction du fait que vous avez un nom de table variable avec (au moins) deux noms de tables, il serait peut-être préférable de créer une méthode qui prend l'entité que vous stockez et retourne une instruction préparée.

PreparedStatement p = createStatement(table); 
1

Ceci est techniquement possible avec une solution de contournement, mais très mauvaise pratique.

String sql = "IF ? = 99\n"; 
sql += "SELECT * FROM first_table\n"; 
sql += "ELSE\n"; 
sql += "SELECT * FROM second_table"; 
PreparedStatement ps = con.prepareStatement(sql); 

Et puis quand vous voulez sélectionner first_table vous définissez le paramètre avec

ps.setInt(1, 99); 

Ou sinon, vous définissez à autre chose.

Questions connexes