在我的Java应用程序中,我必须使用WHERE子句从Oracle数据库中选择数据。我将使用准备好的声明。 哪个更好,我应该使用
SELECT column_name FROM table_name WHERE column_name = ?
SELECT column_name FROM table_name WHERE column_name = ?
SELECT column_name FROM table_name WHERE column_name = ?
.
.
.
SELECT column_name FROM table_name WHERE column_name = ?
或
SELECT column_name FROM table_name WHERE column_name IN (?, ?, ?, ... ?)
我需要在WHERE子句中使用的数据计数可以在01到500之间变化。
答案 0 :(得分:2)
每个查询执行都带有一些处理/解析/网络开销,因此通过在IN
子句中提供值列表,在单个查询中检索多行的速度可以快一个数量级。例如,Oracle必须执行"soft parse"(语法和语义验证,缓存查找),即使查询是可重用的(使用绑定变量),如第一个示例中的情况。
您应该注意,您可以在Oracle的IN
子句中包含固定的1000个绑定变量限制。
答案 1 :(得分:0)
如果可能值的数量从1到500不等,那么准备这500个查询可能不值得。我只会每次生成纯SQL(例如SELECT column_name FROM table_name WHERE column_name IN (23,29,31,37)
)并将其作为普通语句执行。我知道它反对总是准备查询和使用绑定的规则(确保你的代码不受SQL注入攻击)但是规则被破坏了。
答案 2 :(得分:0)
实际上,in()运算符可以更快,但带有(可忽略的)解析成本,加上使用多达500个元素的限制,加上总sql查询文本大小的限制。所以它足够好,但不是火箭证明:)
防火解决方案是在单独的调用中传递任意数量的参数,然后使用视图(或任何其他方式)在SQL中表示它们并在您的where条件中使用。
这里有一个蛮力变体http://tkyte.blogspot.hu/2006/06/varying-in-lists.html
但是,如果你可以使用PL / SQL,那么这个烂摊子就会变得非常整洁。
function getCustomers(in_customerIdList clob) return sys_refcursor is
begin
aux_in_list.parse(in_customerIdList);
open res for
select *
from customer c,
in_list v
where c.customer_id=v.token;
return res;
end;
然后,您可以在参数中传递任意数量的逗号分隔客户ID,并且:
这里的诀窍是:
视图如下:
create or replace view in_list
as
select
trim( substr (txt,
instr (txt, ',', 1, level ) + 1,
instr (txt, ',', 1, level+1)
- instr (txt, ',', 1, level) -1 ) ) as token
from (select ','||aux_in_list.getpayload||',' txt from dual)
connect by level <= length(aux_in_list.getpayload)-length(replace(aux_in_list.getpayload,',',''))+1
其中aux_in_list.getpayload引用原始输入字符串。