0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ストアドプロシージャ/ファンクションに配列を渡す

Last updated at Posted at 2021-02-04

はじめに

  • 固定の数ではないパラメータをプロシージャに渡そうとして試行錯誤しました。
  • 実装方法等を纏めます。
  • ストアドプロシージャで確認していますが、ストアドファンクションでも同じだと思います。

環境

  • 環境は以下です。おそらくこんな環境では開発しないと思いますが参考程度に。本質は変わらないとは思います。(jdkのバージョンが違っても本質は同じではないかと思います)
項目 バージョン
JDK 1.5
Oracle 11

やりたいこと

  • Oracleインスタンスに定義された、ストアドプロシージャをjavaから呼ぶ。
  • ストアドプロシージャに渡すパラメータとして、数値の配列を渡したい。

実装

各種定義

  • テスト用の簡単なテーブルを用意します。定義は以下です。
create table ARRAY_TEST (
  id number,
  name varchar2(256)
);
  • TYPE_TABLE_OF_NUMBERという型を作成します。定義は以下です。
create or replace TYPE "TYPE_TABLE_OF_NUMBER" AS TABLE OF NUMBER

実装

プロシージャ

  • プロシージャは以下のとおり。
  • 変数名などはいい加減です。
create or replace procedure arrayTest(idsin  TYPE_TABLE_OF_NUMBER)
  as
  begin
    FOR i IN ids.first..ids.last LOOP
      insert into ARRAY_TEST (id,name) values (ids(i),'dummy');
    END LOOP;
    commit;
  end;

java側

  • java側のコードは以下。
  • パッケージ宣言やimportなどは省略しています。
  • 接続情報は伏せてあります。
private static void executeStoredProcedure() throws SQLException {
	try {
		Class.forName("oracle.jdbc.driver.OracleDriver");
	} catch (ClassNotFoundException e1) {
		e1.printStackTrace();
	}
	final String URL = "jdbc:oracle:thin:@xx.xx.xx.xx:port:sid";
	final String USER = "user";
	final String PASS = "pass";
	String procedureSQL = "{call arrayTest(?)}";
	Connection conn = DriverManager.getConnection(URL,USER,PASS);
	try {
		CallableStatement cs = conn.prepareCall(procedureSQL);
		ArrayList ids = new ArrayList<Integer>();
		ids.add(1);
		ids.add(2);
		ids.add(3);
		ids.add(4);
		ArrayDescriptor arrayDescriptor= ArrayDescriptor.createDescriptor(
				"TYPE_TABLE_OF_NUMBER", conn);
		ARRAY arrayParameter = new ARRAY(arrayDescriptor, conn, ids.toArray()); 
		cs.setArray(1, arrayParameter);
		cs.execute();
	} catch (SQLException e) {
		e.printStackTrace();
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		System.out.println("処理が完了しました");
	}
}

補足

  • 古いjdkだと、Class.forName("oracle.jdbc.driver.OracleDriver")を呼ばないと接続できないようです。
  • createDescriptorであらかじめ定義された型の名称を渡しています。ここがパッケージ内に定義された型の場合はこの方法では動かないようです。
    • <スキーマ名>.<パッケージ名>.<型名>という指定をしても見つからないというエラーになる。
  • 以下のサイトに解決方法があるようなのですが、このやり方はたしかによくないと思います。(試していない)

参考にしたサイト

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?