database - 使用 SQL :2008 standard on PostgreSQL using prepared statements 限制结果

标签 database postgresql jdbc prepared-statement limit

在编写一个示例来测试 PostgreSQL 对 SQL:2008 结果集限制功能的支持时,我意识到此语法不适用于准备好的语句:

SELECT pc.id AS pc_id, p.id AS p_id  
FROM post_comment pc 
INNER JOIN post p ON p.id = pc.post_id 
ORDER BY pc.id 
OFFSET ? ROWS 
FETCH FIRST ? ROWS ONLY;

虽然对于使用文字的静态语句来说没问题,但使用准备好的语句会抛出:

org.postgresql.util.PSQLException: ERROR: syntax error at or near "$2" Position: 140 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182) ~[postgresql-9.4-1202-jdbc41.jar:9.4] at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911) ~[postgresql-9.4-1202-jdbc41.jar:9.4] at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) ~[postgresql-9.4-1202-jdbc41.jar:9.4] at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:615) ~[postgresql-9.4-1202-jdbc41.jar:9.4] at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:465) ~[postgresql-9.4-1202-jdbc41.jar:9.4] at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:458) ~[postgresql-9.4-1202-jdbc41.jar:9.4]

如果 SQL 查询更改为:

SELECT pc.id AS pc_id, p.id AS p_id  
FROM post_comment pc 
INNER JOIN post p ON p.id = pc.post_id 
ORDER BY pc.id 
OFFSET ? ROWS 
FETCH FIRST (?) ROWS ONLY;

括号似乎可以解决问题,并且绑定(bind)参数也被考虑在内。

这是一个错误还是只是一个实现细节?

测试可在GitHub上进行

最佳答案

TL;DR:实现细节。


这不是 JDBC 驱动程序问题,而是数据库级别的问题。

test=> SELECT 1 OFFSET 1 ROWS FETCH FIRST 1 ROWS ONLY;
 ?column? 
----------
(0 rows)

test=> PREPARE stmt(integer, integer) AS SELECT 1 OFFSET $1 ROWS FETCH FIRST $2 ROWS ONLY;
ERROR:  syntax error at or near "$2"
LINE 1: ..., integer) AS SELECT 1 OFFSET $1 ROWS FETCH FIRST $2 ROWS ON...

问题是 FETCH FIRST n ROWS ONLY 的参数没有被解析为作为参数放置候选的文字。

src/backend/parser/gram.y中:

          /* SQL:2008 syntax */
          | FETCH first_or_next opt_select_fetch_first_value row_or_rows ONLY
              { $$ = $3; }

  /*                          
   * Allowing full expressions without parentheses causes various parsing
   * problems with the trailing ROW/ROWS key words.  SQL only calls for
   * constants, so we allow the rest only with parentheses.  If omitted,
   * default to 1.
   */
  opt_select_fetch_first_value:
              SignedIconst                        { $$ = makeIntConst($1, @1); }
              | '(' a_expr ')'                    { $$ = $2; }
              | /*EMPTY*/                         { $$ = makeIntConst(1, -1); }
          ;

表明这实际上是有意为之,并且需要括号来消除参数使用的歧义,但 SQL:2008 并不要求支持将其作为查询参数。

如果要提供参数,请使用括号。

关于database - 使用 SQL :2008 standard on PostgreSQL using prepared statements 限制结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32782524/

相关文章:

sql - 如何使用键值对列表查询数据库

database - 如何解析大量PDF

node.js - 如何在 Sequelize 中使用 Postgres 的 BIGSERIAL?

java - 无法加载类 [org.postgresql.Driver]

java - 如何防止我的 jComboBox 重置?

javascript - 在 MySql javascript 中更新数据

php - 如何在mysql结果之间放置广告?

windows - 如何使用命令提示符在 Windows 上安装 PostgreSQL?

sql - 如何在 Postgre 中返回主列名?

java - 创建 jdbc 连接的动态代理以覆盖提交或回滚方法