prepareStatement()似乎是剥离分号

时间:2012-06-06 12:30:11

标签: java prepared-statement

我正在尝试使用以下内容执行准备好的语句:

dbaBean.setPrepStmt(dbaBean.getConn().prepareStatement(
    "SELECT id, author, title, url, article_text, date_created " +
            "FROM articles WHERE " +
            "(EXTRACT(YEAR FROM date_created) = ? OR ? is null) " +
            "AND (EXTRACT(MONTH FROM date_created) = ? OR ? is null) " +
            "AND (EXTRACT(DAY FROM date_created) = ? OR ? is null) AND " +
            "(url = ? OR ? is null) " +
            "ORDER BY date_created DESC;"));

dbaBean.getPrepStmt().setString(1, year);
dbaBean.getPrepStmt().setString(2, year);
dbaBean.getPrepStmt().setString(3, month);
dbaBean.getPrepStmt().setString(4, month);
dbaBean.getPrepStmt().setString(5, day);
dbaBean.getPrepStmt().setString(6, day);
dbaBean.getPrepStmt().setString(7, URL);
dbaBean.getPrepStmt().setString(8, URL);

System.out.println(dbaBean.getPrepStmt().toString());

dbaBean是一个提供连接和准备好的语句的对象。它根本不做任何操作。

我已经非常成功地将上述代码用于其他方法,并且完全没有遇到任何问题。现在这个函数似乎是在末尾剥去分号,例如这是使用System.out行输出的:

SELECT id, author, title, url, article_text, date_created FROM articles WHERE (EXTRACT(YEAR FROM date_created) = NULL OR NULL is null) AND (EXTRACT(MONTH FROM date_created) = NULL OR NULL is null) AND (EXTRACT(DAY FROM date_created) = NULL OR NULL is null) AND (url = 'someurl' OR 'someurl' is null) ORDER BY date_created desc

注意缺少分号。

我尝试添加第二个分号,它也被“吃掉”了。

其他更改被传播正确(例如,要选择的其他字段)。

如果重要的话,这是postgresql。

编辑:我关心,因为我在运行此查询时遇到错误,我认为删除分号是潜在的罪魁祸首。下面的答案似乎表明情况并非如此,我需要寻找其他地方。

2 个答案:

答案 0 :(得分:4)

我花了几分钟时间浏览Postgresql JDBC驱动程序源代码,看来发生的情况如下:

  • 创建预准备语句后,驱动程序会进行部分解析,将SQL拆分为语句,查找占位符并(我认为)删除任何注释。

  • 解析的结果存储在PreparedStatement对象中一系列片段。

  • 如果在语句上调用toString(),该方法会重构SQL,插入占位符的值,并在每个语句之间添加分号 ...如果有多个陈述。

所以,消失的分号是一个特征,而不是一个bug。 JDBC规范中的任何内容都不要求toString()方法以原始形式提供查询...或者以任何形式提供查询。此外,通常的做法是使用(至少对于Postgresql)在为JDBC编写SQL时不要使用尾随的分号。

答案 1 :(得分:3)

preparedStatement(String sql)方法接受输入String并创建一个CallableStatement对象来调用数据库存储过程。

在CallableStatement对象初始化期间,jdbc驱动程序将sql字符串转换为系统的本机SQL语法。

由于分号是Postgresql的分隔符,您可以假设它被jdbc驱动程序删除,并且如果使用其他jdbc驱动程序实现可能会有所不同。所以最好的办法就是从SQL字符串中删除它。