Java中使用PreparedStatement查询Dishes表时ResultSet返回列名而非实际值的问题
问题分析
你遇到的核心问题是PreparedStatement的占位符(?)不能用来动态指定列名——它只能用于替换SQL语句中的参数值(比如WHERE子句里的条件值),而不能替换表名、列名这类SQL标识符。
你写的select ? as smt from DISHES where ESTID=?,当你把Wednesday传入第一个占位符时,SQL实际执行的是类似select 'Wednesday' as smt from DISHES where ESTID=xxx,所以ResultSet里的smt值就是字符串Wednesday,而不是对应列的菜品数据。
解决方案
方法1:动态拼接列名(适合当前场景)
因为你的day值是从Calendar获取的,属于可控输入(不会来自用户提交的不可信数据),所以可以直接拼接列名到SQL语句中:
// 先获取正确的星期列名(比如"Wednesday") String day = ...; // 你的Calendar逻辑获取的星期名称 String selectD = String.format("select `%s` as smt from DISHES where ESTID=?", day); prestatement = dbConnection.prepareStatement(selectD); prestatement.setInt(1, resID); // 这里注意占位符索引变成1了 rs = prestatement.executeQuery(); if(rs.next()){ String Dish = rs.getString("smt"); EstInfo.setText("Today's dish is "+Dish); }else{ System.out.println("Found nothing in DISHES"); }
注意:如果
day可能包含特殊字符或者来自不可信输入,这种方法会有SQL注入风险,但你的场景是从Calendar获取的固定星期名称,所以安全。
方法2:使用CASE语句(更安全,适合不可信输入场景)
如果担心SQL注入(比如未来day可能来自用户输入),可以用CASE语句来映射列名:
String day = ...; String selectD = "select " + "CASE ? " + "WHEN 'Monday' THEN Monday " + "WHEN 'Tuesday' THEN Tuesday " + "WHEN 'Wednesday' THEN Wednesday " + "WHEN 'Thursday' THEN Thursday " + "WHEN 'Friday' THEN Friday " + "WHEN 'Saturday' THEN Saturday " + "WHEN 'Sunday' THEN Sunday " + "END as smt " + "from DISHES where ESTID=?"; prestatement = dbConnection.prepareStatement(selectD); prestatement.setString(1, day); prestatement.setInt(2, resID); rs = prestatement.executeQuery(); // 后续处理逻辑和之前一样
这种方式既保留了PreparedStatement的参数化优势,又实现了动态列的查询,完全避免SQL注入风险。
额外提示
- 确认你的
DISHES表的列名和Calendar返回的星期名称完全一致(大小写也要匹配,比如数据库列是wednesday但你传的是Wednesday会查不到)。 - 如果数据库对大小写敏感,建议统一列名和代码中的星期名称格式(比如都用小写或都用首字母大写)。
内容的提问来源于stack exchange,提问作者TehKonnos
相关产品推荐
相关产品推荐

