OFFSET N FETCH FIRST M ROWS 与 JDBC 和 PostgreSQL 不工作
Posted
技术标签:
【中文标题】OFFSET N FETCH FIRST M ROWS 与 JDBC 和 PostgreSQL 不工作【英文标题】:OFFSET N FETCH FIRST M ROWS with JDBC and PostgreSQL not working 【发布时间】:2018-05-16 13:04:33 【问题描述】:我正在尝试使用 JDBC 和 PostgreSQL 进行查询,但我遇到了在任何文档中都找不到的奇怪情况。
如果我通过 pgAdmin 和 H2(我将其用于我的应用程序的单元测试)执行以下查询,则以下查询有效,但如果我通过 JDBC 执行它,则会出现语法错误:
Queries.SELECT_SQL
SELECT columns
FROM Table
LEFT JOIN TableToJoin1
LEFT JOIN TableToJoin2
LEFT JOIN TableToJoin3
JOIN TableToJoin4
Queries.ENDING_PAGING_STATEMENT_SQL
OFFSET ? ROWS FETCH FIRST ? ROWS ONLY
SELECT
查询是正确的,并且可以使用任何方式正常工作,问题是当我将两个查询放在一起时,即 SELECT
语句以及 OFFSET
和 FETCH FIRST
。
这就是我通过JDBC
执行查询的方式:
// Receive offset and limit as argument.
try (final PreparedStatement selectStatement = connection
.prepareStatement(Queries.SELECT_SQL + Queries.ENDING_PAGING_STATEMENT_SQL))
selectStatement.setInt(Queries.PAGING_ENDING_STATEMENT_OFFSET_ARGUMENT_POSITION, offset);
selectStatement.setInt(Queries.PAGING_ENDING_STATEMENT_LIMIT_ARGUMENT_POSITION, limit);
final ResultSet resultSet = bookSelectStatement.executeQuery();
...
这里是抛出异常的消息:
org.postgresql.util.PSQLException: ERROR: syntax error at or near "$2"
如果我调用selectStatement.toString()
进行调试,我会收到完全符合我预期的查询。
如果我将OFFSET N ROWS FETCH FIRST M ROWS ONLY
更改为OFFSET N LIMIT M
,它将通过JDBC 正常工作。
最简单的解决方案是在上面进行简单的更改,但我的部分任务是使用此 FETCH FIRST M ROWS ONLY
语句进行查询。
那么,你们能帮我看看我是否做错了,或者根本没有办法在 JDBC for PostgreSQL 上使用FETCH FIRST
?提供一些示例或对任何有帮助的文档的一些参考。
我注意到FETCH FIRST
在PostgreSQL Documentation: Queries - Offset and Limit 上不存在,但由于它通过 pgAdmin 工作,我不知道为什么我在使用 JDBC 时会遇到任何问题。
非常感谢!
【问题讨论】:
fetch first
是关于 select
statement 的章节中的文档 - 看起来像文档错误
您也不能在PreparedStatement
中提供限制/偏移作为可分配参数。实际上,这可能不再适用,取决于驱动程序。
谢谢@a_horse_with_no_name,它被隐藏在索引中,但看起来我对查询没有做错任何事情。
@Kayaman,但是如果我将OFFSET N ROWS FETCH FIRST M ROWS ONLY
更改为OFFSET N LIMIT M
它将正常工作,而无需更改PreparedStatement
上的任何内容,为什么会有所不同?
看来PreparedStatement
确实允许参数化限制/偏移,但我可以发誓我之前遇到过问题。我可能正在考虑一些不允许这样做的混淆层。
【参考方案1】:
我可以重现这个问题。从版本 10 开始,documentation 表示:
在这种语法中,要编写除简单整数常量之外的任何内容作为开始或计数,您必须在其周围加上括号
当然,这很荒谬。应该允许不带括号的绑定变量 - 大多数数据库都允许它们并且 PostgreSQL 也接受 OFFSET ? LIMIT ?
语法,但看起来好像它们不在 PostgreSQL 对标准 SQL 语法的解释中。所以你必须写:
OFFSET (?) ROWS FETCH FIRST (?) ROWS ONLY
I would consider this a bug, which I've reported here
【讨论】:
哎呀,我正在使用它,我只是忘记写在问题上,谢谢。但不管有没有那个关键字,它都会给我同样的错误。 什么?好的.. 这真的很有帮助,我在上课时没有任何笔记,所以这是新的,出乎意料的。谢谢,现在可以正常使用了! “看起来好像它们不在标准 SQL 语法中” SQL 标准允许文字或参数(但不允许列等),但它不允许允许表达式。从技术上讲,标准甚至不允许使用括号。 (SQL:2016-2 7.17) @a_horse_with_no_name:我已恢复您的更改并添加了清晰的版本指示器。我认为这是一个应该修复的错误,所以将来,手册可能会说一些不同的内容 @MarkRotteveel:是的,修正了我的措辞。我不是这个意思以上是关于OFFSET N FETCH FIRST M ROWS 与 JDBC 和 PostgreSQL 不工作的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server ->> OFFSET & FETCH子句
为啥我不能在我的 SQL Server 上查询 OFFSET/FETCH 查询?