从 SQL 方面,您可以定义一个表类型并使用它来连接您的真实数据,例如:
create type my_array_type as table of number
/
create or replace function f42 (in_array my_array_type)
return sys_refcursor as
rc sys_refcursor;
begin
open rc for
select a.column_value as id,
case when t.id is null then 'missing'
else 'present' end as status
from table(in_array) a
left join t42 t on t.id = a.column_value
order by id;
return rc;
end f42;
/
SQL Fiddle demo 带有包装函数,因此您可以直接查询它,它给出:
ID STATUS
---------- --------------------
1 present
2 present
3 present
4 missing
8 missing
23 present
在Java中,您可以根据表类型定义ARRAY,从Java数组中填充,并直接调用函数;你的单参数绑定变量是ARRAY,你会得到一个可以正常迭代的结果集。
作为Java端的概述:
int[] ids = { 1, 2, 3, 4, 8, 23 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("MY_ARRAY_TYPE",
conn);
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);
cStmt = (OracleCallableStatement) conn.prepareCall("{ call ? := f42(?) }");
cStmt.registerOutParameter(1, OracleTypes.CURSOR);
cStmt.setArray(2, ora_ids);
cStmt.execute();
rSet = (OracleResultSet) cStmt.getCursor(1);
while (rSet.next())
{
System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
}
这给出了:
id 1: present
id 2: present
id 3: present
id 4: missing
id 8: missing
id 23: present
正如 Maheswaran Ravisankar 所提到的,这允许传递任意数量的元素;您不需要知道编译时有多少元素(或处理理论上的最大值),您不受 IN 中允许的最大表达式数或单个分隔字符串的长度的限制,并且您不必组合和分解一个字符串来传递多个值。
正如 ThinkJet 指出的,如果您不想创建自己的表类型,可以使用预定义的集合,demonstrated here;主函数除了参数的声明是一样的:
create or replace function f42 (in_array sys.odcinumberlist)
return sys_refcursor as
...
包装函数填充数组的方式略有不同,但在 Java 端您只需要更改此行:
ArrayDescriptor aDesc =
ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
使用这也意味着(正如 ThinkJet 也指出的那样!)您可以在不定义函数的情况下运行原始的独立查询:
select a.column_value as id,
case when t.id is null then 'missing'
else 'present' end as status
from table(sys.odcinumberlist(1, 2, 3, 4, 8, 23)) a
left join t42 t on t.id = a.column_value
order by id;
(SQL Fiddle).
这意味着您可以直接从 Java 调用查询:
int[] ids = { 1, 2, 3, 4, 8, 23 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);
sql = "select a.column_value as id, "
+ "case when t.id is null then 'missing' "
+ "else 'present' end as status "
+ "from table(?) a "
+ "left join t42 t on t.id = a.column_value "
+ "order by id";
pStmt = (OraclePreparedStatement) conn.prepareStatement(sql);
pStmt.setArray(1, ora_ids);
rSet = (OracleResultSet) pStmt.executeQuery();
while (rSet.next())
{
System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
}
...您可能更喜欢。
还有一个预定义的 ODCIVARCHAR2LIST 类型,如果您实际上是在传递字符串 - 您的原始代码似乎正在处理字符串,即使它们包含数字,所以不确定您真正需要哪个。
因为这些types are defined as VARRAY(32767) 限制为 32k 值,而定义自己的表消除了该限制;但显然,只有当你传递了很多值时,这才重要。