java - 是否可以将 GROUP BY 与绑定(bind)变量一起使用?

标签 java sql oracle jdbc prepared-statement

我想发出如下查询

select max(col1), f(:1, col2) from t group by f(:1, col2)

其中 :1 是一个绑定(bind)变量。使用 PreparedStatement,如果我说

connection.prepareStatement
  ("select max(col1), f(?, col2) from t group by f(?, col2)")

我从 DBMS 得到一个错误,提示 f(?, col2) 不是 GROUP BY 表达式。

通常如何在 JDBC 中解决这个问题?

最佳答案

我建议重新编写语句,以便只有一个绑定(bind)参数。 这种方法有点难看,但返回结果集:

select max(col1) 
     , f_col2
  from (
         select col1
              , f(? ,col2) as f_col2 
           from t
       )
 group
    by f_col2

这个重写的语句只引用了一个绑定(bind)参数,所以现在 DBMS 认为 GROUP BY 子句和 SELECT 列表中的表达式是相同的。

HTH

[编辑]

(我希望有更漂亮的方法,这就是为什么我更喜欢 Oracle 使用的命名绑定(bind)参数方法。使用 Perl DBI 驱动程序,位置参数被转换为实际发送到 Oracle 的语句中的命名参数。)

一开始没看出问题,没看懂原题。 (显然,其他几个人也错过了它。)但是在运行一些测试用例之后,我明白了问题是什么,问题是什么在起作用。

让我看看我是否可以陈述问题:如何让两个单独的(位置)绑定(bind)参数(由 DBMS)处理,就好像它们是对相同(命名的)绑定(bind)参数的两个引用。

DBMS 期望 GROUP BY 中的表达式与 SELECT 列表中的表达式相匹配。但是这两个表达式被认为是不同的,即使这两个表达式是相同的,唯一的区别是每个表达式引用不同的绑定(bind)变量。 (我们可以演示一些至少某些 DBMS 允许的测试用例,但还有更一般的用例会引发异常。)

在这一点上,简短的回答是,这让我难住了。我的建议(可能不是对原始问题的实际答案)是重组查询。

[/编辑]

如果此方法不起作用,或者如果您在解决问题时遇到其他问题,我可以提供更多详细信息。或者如果性能有问题(我可以看到优化器为重写的查询选择了不同的计划,即使它返回了指定的结果集。为了进一步测试,我们真的需要知道什么 DBMS,什么驱动程序,统计等)

编辑(八年半后)

再次尝试重写查询。同样,我想出的唯一解决方案是使用一个绑定(bind)占位符的查询。这一次,我们将它粘贴到一个返回单行的内联 View 中,并将其连接到 t。我可以看到它在做什么;我不确定 Oracle 优化器将如何看待这一点。我们可能希望(或需要)进行显式转换,例如TO_NUMBER(?) AS paramTO_DATE(?,'...') AS paramTO_CHAR(?) AS param,取决于绑定(bind)参数的数据类型,以及我们希望从 View 返回的数据类型。)

这就是我在 MySQL 中的做法。我回答中的原始查询在内联 View (MySQL 派生表)中执行连接操作。如果可以避免,我们希望避免具体化 hughjass 派生表。话又说回来,只要 sql_mode 不包括 ONLY_FULL_GROUP_BY,MySQL 可能会让原始查询滑动。 MySQL 也会让我们删除 FROM DUAL)

  SELECT MAX(t.col1)
       , f( v.param ,t.col2)
    FROM t
   CROSS
    JOIN ( SELECT ? AS param FROM DUAL) v
   GROUP
      BY f( v.param ,t.col2)

根据 MadusankaD 的回答,在过去的八年中,Oracle 添加了对在 JDBC 驱动程序中重用相同命名的绑定(bind)参数的支持,并保留等价性。 (我还没有测试过,但如果现在可以,那就太好了。)

关于java - 是否可以将 GROUP BY 与绑定(bind)变量一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/941034/

相关文章:

java - 在 eclipse 中离线安装 google app engine 插件

mysql - 如何获取具有特定值的下一条记录,然后返回一条记录以从日志中计算 session 持续时间?

php - 网络抓取转化率并绘制图表

mysql - 使用联接、分组依据和全文的 where 子句中的未知列 xxx

java - 为什么我收到 : [Oracle][ODBC][Ora]ORA-00904: invalid identifier

oracle - 如何编写一个基于自动递增值的Oracle触发器?

java - 与类(Class)斗争,延伸和实现

java - 是否可以创建一个包含单个 jar 的类加载器?

sql - 触发器编译但不插入行

java - 使用 JDBC 进行批量插入的有效方法