是否可以将GROUP BY与绑定变量一起使用?

Apo*_*isp 5 java sql oracle jdbc prepared-statement

我想发出如下的查询

select max(col1), f(:1, col2) from t group by f(:1, col2)
Run Code Online (Sandbox Code Playgroud)

哪里:1是绑定变量.使用PreparedStatement,如果我说

connection.prepareStatement
  ("select max(col1), f(?, col2) from t group by f(?, col2)")
Run Code Online (Sandbox Code Playgroud)

我收到DBMS抱怨的错误,f(?, col2)它不是GROUP BY表达式.

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

spe*_*593 8

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

select max(col1) 
     , f_col2
  from (
         select col1
              , f(? ,col2) as f_col2 
           from t
       )
 group
    by f_col2
Run Code Online (Sandbox Code Playgroud)

这个重写的语句只引用了一个绑定参数,所以现在DBMS看到GROUP BY子句中的表达式和SELECT列表是相同的.

HTH

[编辑]

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

我一开始没有看到问题,我不明白原来的问题.(显然,其他几个人也错过了它.)但是在运行了一些测试用例之后,我突然意识到问题是什么,问题是什么.

让我看看我是否可以陈述问题:如何获得两个独立的(位置)绑定参数(由DBMS处理),好像它是对同一(命名)绑定参数的两个引用.

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

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

[/编辑]

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

编辑(八年半之后)

另一次尝试重写查询.同样,我提出的唯一解决方案是使用一个绑定占位符的查询.这一次,我们将其粘贴到一个返回单行的内联视图中,并将其连接到t.我可以看到它在做什么; 我不确定Oracle优化器将如何看待它.我们可能希望(或需要)做一个明确的转换例如TO_NUMBER(?) AS param,TO_DATE(?,'...') AS param,TO_CHAR(?) AS param,根据绑定参数的数据类型,我们要返回从视图中的数据类型.)

这就是我在MySQL中的表现.我的回答中的原始查询在内联视图(MySQL 派生表)中进行了连接操作.如果我们能够避免它,我们希望避免实现一个hughjass派生表.然后,MySQL可能会让原始查询滑动,只要sql_mode不包括ONLY_FULL_GROUP_BY.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)
Run Code Online (Sandbox Code Playgroud)

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