【问题标题】:JDBC PreparedStatement Seems to Ignore PlaceholderJDBC PreparedStatement 似乎忽略占位符
【发布时间】: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

为什么在处理查询时? 占位符没有被替换?

【问题讨论】:

    标签: java sql sqlite jdbc


    【解决方案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 开头的表名;这似乎也很好。谢谢你,乔恩。我不知道占位符的限制!
    猜你喜欢
    • 2018-05-16
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 2011-07-09
    • 2016-06-25
    • 1970-01-01
    • 2021-10-28
    • 2016-09-30
    相关资源
    最近更新 更多