我正在尝试使用以下内容执行准备好的语句:
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。
编辑:我关心,因为我在运行此查询时遇到错误,我认为删除分号是潜在的罪魁祸首。下面的答案似乎表明情况并非如此,我需要寻找其他地方。
答案 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字符串中删除它。