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;
/
ラッパー関数を使用したSQLFiddleデモ。直接クエリを実行できるため、次のようになります。
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
で許可される式の最大数に制限されません。 または、1つの区切られた文字列の長さで、複数の値を渡すために文字列を作成および分解する必要はありません。
ThinkJetが指摘したように、独自のテーブルタイプを作成したくない場合は、ここで示す事前定義されたコレクションを使用できます。パラメータの宣言を除けば、主な機能は同じです:
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フィドル)。
つまり、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の値に制限されます。しかし、明らかにそれは、多くの値を渡す場合にのみ重要です。