От страна на 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 с функция за обвивка, за да можете да я заявите директно, което дава:
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
Както споменава Махесваран Рависанкар, това позволява преминаването на произволен брой елементи; не е нужно да знаете колко елемента има по време на компилиране (или да се справяте с теоретичен максимум), не сте ограничени от максималния брой изрази, разрешени в IN
или по дължината на единичен разделен низ и не е нужно да съставяте и декомпозирате низ, за да предадете множество стойности.
Както ThinkJet посочи, ако не искате да създавате свой собствен тип таблица, можете да използвате предварително дефинирана колекция, демонстрирана тук; основната функция е същата, освен декларацията на параметъра:
create or replace function f42 (in_array sys.odcinumberlist)
return sys_refcursor as
...
Функцията wrapper попълва масива малко по-различно, но от страна на 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
напишете също, ако всъщност предавате низове - оригиналният ви код изглежда работи с низове, въпреки че съдържат числа, така че не сте сигурни от кои наистина се нуждаете.
Тъй като тези типове са дефинирани като VARRAY(32767)
сте ограничени до 32k стойности, докато дефинирането на вашата собствена таблица премахва това ограничение; но очевидно това има значение само ако предавате много стойности.