我想发出如下查询
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 param
,TO_DATE(?,'...') AS param
,TO_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/