in()操作符的局限性是万恶之源。
它适用于不重要的情况,您可以将其扩展为“自动生成准备好的语句”,但它总是有其局限性。
如果您正在创建具有可变数量参数的语句,那么每次调用都会产生SQL解析开销
在许多平台上,in()操作符的参数数量是有限的
在所有平台上,总SQL文本大小是有限的,因此不可能为in参数发送2000个占位符
向下发送1000-10k的绑定变量是不可能的,因为JDBC驱动程序有其局限性
在某些情况下,in()方法已经足够好了,但还不能防火箭:)
最可靠的解决方案是在一个单独的调用中传递任意数量的参数(例如,通过传递一组参数),然后用一个视图(或任何其他方式)在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,并且:
将得到没有解析延迟,因为SQL选择是稳定的
没有流水线函数的复杂性——它只是一个查询
SQL使用一个简单的连接,而不是一个IN操作符,这是相当快的
毕竟,不使用任何普通的select或DML访问数据库是一个很好的经验法则,因为它是Oracle,它提供了比MySQL或类似的简单数据库引擎多得多的东西。PL/SQL允许您以一种有效的方式从应用程序域模型中隐藏存储模型。
这里的技巧是:
我们需要一个接受长字符串的调用,并存储在db会话可以访问它的地方(例如简单的包变量,或dbms_session.set_context)
然后我们需要一个视图,它可以将这些数据解析为行
然后你有一个包含你要查询的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引用原始的输入字符串。
一个可能的方法是传递pl/sql数组(仅由Oracle支持),但是你不能在纯sql中使用它们,因此总是需要一个转换步骤。这种转换不能在SQL中完成,因此,传递一个带有字符串中所有参数的clob并在视图中进行转换是最有效的解决方案。