Du côté SQL, vous pouvez définir un type de table et l'utiliser pour joindre vos données réelles, quelque chose comme :
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;
/
Démo SQL Fiddle avec une fonction wrapper pour que vous puissiez l'interroger directement, ce qui donne :
ID STATUS
---------- --------------------
1 present
2 present
3 present
4 missing
8 missing
23 present
Depuis Java, vous pouvez définir un ARRAY
en fonction du type de table, remplir à partir d'un tableau Java et appeler directement la fonction ; votre variable de liaison à paramètre unique est le ARRAY
, et vous récupérez un ensemble de résultats sur lequel vous pouvez itérer normalement.
En guise d'aperçu du côté 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));
}
Ce qui donne :
id 1: present
id 2: present
id 3: present
id 4: missing
id 8: missing
id 23: present
Comme Maheswaran Ravisankar le mentionne, cela permet de passer n'importe quel nombre d'éléments; vous n'avez pas besoin de savoir combien d'éléments il y a au moment de la compilation (ou de gérer un maximum théorique), vous n'êtes pas limité par le nombre maximum d'expressions autorisées dans un IN
ou par la longueur d'une seule chaîne délimitée, et vous n'avez pas à composer et décomposer une chaîne pour transmettre plusieurs valeurs.
Comme l'a souligné ThinkJet, si vous ne souhaitez pas créer votre propre type de table, vous pouvez utiliser une collection prédéfinie, illustrée ici; la fonction main est la même hormis la déclaration du paramètre :
create or replace function f42 (in_array sys.odcinumberlist)
return sys_refcursor as
...
La fonction wrapper remplit le tableau légèrement différemment, mais du côté Java, vous n'avez qu'à modifier cette ligne :
ArrayDescriptor aDesc =
ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
L'utilisation de cela signifie également (comme ThinkJet l'a également souligné !) que vous pouvez exécuter votre requête autonome d'origine sans définir de fonction :
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;
(Violon SQL).
Et cela signifie que vous pouvez appeler la requête directement depuis 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));
}
... que vous préférez peut-être.
Il existe un ODCIVARCHAR2LIST
prédéfini tapez aussi, si vous passez réellement des chaînes - votre code d'origine semble fonctionner avec des chaînes même si elles contiennent des nombres, donc vous ne savez pas ce dont vous avez vraiment besoin.
Parce que ces types sont définis comme VARRAY(32767)
vous êtes limité à 32 000 valeurs, tandis que la définition de votre propre table supprime cette restriction ; mais évidemment cela n'a d'importance que si vous transmettez beaucoup de valeurs.