JDBC PreparedStatement 似乎忽略占位符
Posted
技术标签:
【中文标题】JDBC PreparedStatement 似乎忽略占位符【英文标题】:JDBC PreparedStatement Seems to Ignore Placeholder 【发布时间】:2017-09-22 17:13:48 【问题描述】:鉴于PreparedStatement
的以下代码,我使用占位符 (?) 来填充 String
:
String sql = "SELECT SUM(Premium), SUM(AgentComm)\n" +
"FROM \"?_KLCommissions\" \n" +
"WHERE AgentCode = \"?\";";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, year);
preparedStatement.setString(2, agent.getAgentNumber());
ResultSet resultSet = preparedStatement.executeQuery();
但是,在执行查询时,我收到一条 SQL 错误:no such table: ?_KLCommissions
。
为什么在处理查询时?
占位符没有被替换?
【问题讨论】:
【参考方案1】:双引号中包含它,这意味着它不是占位符 - 它只是值的一部分。
除此之外,大多数 SQL 数据库不允许您将参数用于表名和列名等参数 - 只有 值 可以参数化。所以你可能需要直接构建表名部分,然后使用
WHERE AgentCode = ?
对于代理代码 - 因此您只需设置一个参数。所以像:
String tableName = year + "_KLCommissions";
// TODO: Put validation here unless you already have *complete confidence*
// that the value of "year" can't be messed around with.
String sql = "SELECT SUM(Premium), SUM(AgentComm) " +
"FROM " + tableName + " " +
"WHERE AgentCode = ?";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, agent.getAgentNumber());
ResultSet resultSet = preparedStatement.executeQuery();
请注意那里的 TODO - 您真的不希望用户能够为 year
提供任意值,因为这样他们就可以在您的查询中添加任意 SQL。
【讨论】:
因此,例如,如果我需要使用不同的年份多次运行该语句,我实际上需要多个语句来代替吗? @Zephyr:是的,你会的。 请注意,SQLite 不允许表名以数字开头而不用双引号转义名称。 @MickMnemonic 我使用单引号以 int 开头的表名;这似乎也很好。谢谢你,乔恩。我不知道占位符的限制!以上是关于JDBC PreparedStatement 似乎忽略占位符的主要内容,如果未能解决你的问题,请参考以下文章
Java -- JDBC 学习--PreparedStatement
JDBC - 语句、PreparedStatement、CallableStatement 和缓存
JDBC封装学习笔记---面向对象的JDBC,使用preparedStatement