8.1 トップレベルからのJavaのコール
SQLのCALL文を使用すると、トップレベルで公開されたJavaメソッドを、PL/SQLパッケージまたはSQLオブジェクト型でコールできます。SQL*Plusでは、次の構文を使用してCALL文を対話形式で実行できます。
                  
CALL [schema_name.][{package_name | object_type_name}][@dblink_name]
  { procedure_name ([param[, param]...])
   | function_name ([param[, param]...]) INTO :host_variable};
paramは次の構文で表されます。
                  
{literal | :host_variable}
ホスト変数は、ホスト環境で宣言された変数です。このホスト変数には接頭辞としてコロンを付ける必要があります。次の例は、同じCALL文ではホスト変数を2度使用できないこと、およびパラメータのないサブプログラムは空のパラメータ・リストを使用してコールする必要があることを示しています。
                  
CALL swap(:x, :x); -- illegal, duplicate host variables CALL balance() INTO :current_balance; -- () required
この項の内容は次のとおりです。
8.1.1 出力のリダイレクト
サーバーでのデフォルトの出力デバイスは、ユーザー・スクリーンではなくトレース・ファイルです。このため、System.outおよびSystem.errは、現行のトレース・ファイルに出力されます。出力をSQL*Plusテキスト・バッファにリダイレクトするには、次のようにDBMS_JAVAパッケージのset_output()プロシージャをコールする必要があります。
                     
SQL> SET SERVEROUTPUT ON SQL> CALL dbms_java.set_output(2000);
最小バッファ・サイズは2,000バイト(デフォルト・サイズ)で、最大バッファ・サイズは1,000,000バイトです。次の例では、バッファ・サイズを5,000バイトに増やしています。
SQL> SET SERVEROUTPUT ON SIZE 5000 SQL> CALL dbms_java.set_output(5000);
出力はストアド・プロシージャの終了時に表示されます。
8.1.2 トップレベルからのJavaストアド・プロシージャのコールの例
例8-1 簡単なJDBCストアド・プロシージャ
次の例にあるmain()メソッドは、データベース表の名前(employeesなど)、および条件(salary > 1500など)を指定するオプションのWHERE句を受け入れます。条件を省略した場合、メソッドは表からすべての行を削除し、条件を指定した場合は、その条件を満たす行のみを削除します。
                     
import java.sql.*;
import oracle.jdbc.*;
public class Deleter
{
  public static void main (String[] args) throws SQLException
  {
    Connection conn = DriverManager.getConnection("jdbc:default:connection:");
    String sql = "DELETE FROM " + args[0];
    if (args.length > 1)
      sql += " WHERE " + args[1];
    try
    {
      Statement stmt = conn.createStatement();
      stmt.executeUpdate(sql);
      stmt.close();
    }
    catch (SQLException e)
    {
      System.err.println(e.getMessage());
    }
  }
}
main()メソッドには、1つまたは2つの引数を指定できます。通常は、DEFAULT句を使用して、PL/SQLサブプログラムに渡す引数の数を変更します。ただし、この句はコール仕様では使用できません。そのため、次のように2つのパッケージ・プロシージャをオーバーロードする必要があります。
                     
CREATE OR REPLACE PACKAGE pkg AS PROCEDURE delete_rows (table_name VARCHAR2); PROCEDURE delete_rows (table_name VARCHAR2, condition VARCHAR2); END; CREATE OR REPLACE PACKAGE BODY pkg AS PROCEDURE delete_rows (table_name VARCHAR2) AS LANGUAGE JAVA NAME 'Deleter.main(java.lang.String[])'; PROCEDURE delete_rows (table_name VARCHAR2, condition VARCHAR2) AS LANGUAGE JAVA NAME 'Deleter.main(java.lang.String[])'; END;
これで、次のようにdelete_rowsプロシージャをコールできます。
                     
SQL> CALL pkg.delete_rows('employees', 'salary > 1500');
Call completed.
SQL> SELECT first_name, salary FROM employees;
FIRST_NAME  SALARY
--------- --------
SMITH          800
WARD          1250
MARTIN        1250
TURNER        1500
ADAMS         1100
JAMES          950
MILLER        1300
7 rows selected.
注意:
トップレベルのプロシージャはオーバーロードできません。
例8-2 フィボナッチ数列
次のJavaクラスの実行可能ファイルがOracle Databaseに格納されているとします。
public class Fibonacci
{
  public static int fib (int n)
  {
    if (n == 1 || n == 2)
      return 1;
    else
      return fib(n - 1) + fib(n - 2);
  }
}
Fibonacciクラスにはfib()という名前のメソッドが1つあり、このメソッドはn番目のフィボナッチ数を戻します。フィボナッチ数列(1、1、2、3、5、8、13、21、...)は、再帰的です。数列の各項目(2番目の項目より後)は、直前の2つの項目の合計値です。fib()は値を戻すため、次のようにファンクションとして公開する必要があります。
                     
CREATE OR REPLACE FUNCTION fib (n NUMBER) RETURN NUMBER AS LANGUAGE JAVA NAME 'Fibonacci.fib(int) return int';
次に、2つのSQL*Plusホスト変数を宣言し、最初の変数を初期化します。
SQL> VARIABLE n NUMBER SQL> VARIABLE f NUMBER SQL> EXECUTE :n := 7; PL/SQL procedure successfully completed.
これで、fib()ファンクションをコールできます。CALL文では、ホスト変数に接頭辞としてコロンを付ける必要があります。このファンクションは次のようにコールできます。
                     
SQL> CALL fib(:n) INTO :f; Call completed. SQL> PRINT f F ---------- 13