6.3 トップレベルのコール仕様の作成
この項では、SQL*Plusでトップレベルのコール仕様を定義する方法について説明します。
SQL*Plusでは、次の構文を使用してトップレベルのコール仕様を対話形式で定義できます。
CREATE [OR REPLACE] { PROCEDURE procedure_name [(param[, param]...)] | FUNCTION function_name [(param[, param]...)] RETURN sql_type} [AUTHID {DEFINER | CURRENT_USER}] [PARALLEL_ENABLE] [DETERMINISTIC] {IS | AS} LANGUAGE JAVA NAME 'method_fullname (java_type_fullname[, java_type_fullname]...) [return java_type_fullname]';
param
は次の構文で表されます:
parameter_name [IN | OUT | IN OUT] sql_type
-
ストアド・プロシージャをその定義者(
AUTHID DEFINER
)または実行者(AUTHID CURRENT_USER
)のどちらの権限を使用して実行するか -
スキーマ・オブジェクトに対する未修飾の参照を定義者と実行者のどちらのスキーマで解決するか
AUTHID
を指定しない場合、デフォルトの動作はDEFINER
になり、つまり、ストアド・プロシージャは定義者の権限で実行されます。AUTHID
にCURRENT_USER
を指定して、デフォルトの動作をオーバーライドできます。ただし、CURRENT_USER
を指定してloadjava
の-definer
オプションをオーバーライドすることはできません。
PARALLEL_ENABLE
オプションは、ストアド・ファンクションをパラレルDML評価のワーカー・セッションで安全に使用できることを宣言します。メイン・セッションの状態は、ワーカー・セッションとは共有されません。各ワーカー・セッションには独自の状態があり、セッションの開始時に初期化されます。ファンクションの結果はセッション変数の状態に依存する必要はありません。依存すると、セッション間で結果が異なることがあります。
DETERMINISTIC
オプションは、オプティマイザによる冗長なファンクション・コールの回避に役立ちます。以前に同じ引数を使用してストアド・ファンクションがコールされた場合、オプティマイザは以前の結果を使用できます。ファンクションの結果はセッション変数またはスキーマ・オブジェクトの状態に依存する必要はありません。依存すると、コール間で結果が異なることがあります。ファンクション索引、またはクエリー・リライトが可能なマテリアライズド・ビューからのみDETERMINISTIC
ファンクションをコールできます。
NAME
句の文字列は、Javaメソッドを一意に識別します。Javaの完全修飾名とコール仕様パラメータは、位置によってマッピングされ、対応する必要があります。ただし、この規則はmain()
メソッドには適用されません。Javaメソッドが引数を取らない場合は、ファンクションまたはプロシージャ用ではなく、Javaメソッド用の空のパラメータ・リストを作成してください。
NAME
句のmethod_fullname
の部分には、完全にモジュール化されたJavaデータベース・オブジェクト名を指定します。モジュール内に存在するJavaクラスのデータベース・オブジェクト名の形式は次のとおりです:
<module_name>///<class_name>
モジュール内に存在しないJavaクラスのデータベース・オブジェクト名の形式は次のとおりです:
<class_name>
戻り値およびメソッド・シグネチャで使用されるjava_type_fullnames
には、Javaタイプ・クラス名がモジュール常駐の場合でも、module_name
が接頭辞として含まれません。
前述のmethod_fullname
のルールの例外として、method_fullname
で指定されたクラスがシステムに組み込まれたモジュールのメンバーである場合は、method_fullname
のモジュール名の接頭辞を省略できます。たとえば、次のようにコールを指定できます:
create or replace function valueof(n number) return varchar2 as language java name
'java.base///java.lang.String.valueOf(long) return java.lang.String';
次のように記述することもできます:
create or replace function valueof(n number) return varchar2 as language java name
'java.lang.String.valueOf(long) return java.lang.String';
Javaの完全修飾名はドット表記法を使用して記述します。次の例では、完全修飾名はドットで区切り、行をまたいで記述できることを示しています。
artificialIntelligence.neuralNetworks.patternClassification. RadarSignatureClassifier.computeRange()
6.3.1 例
例6-1 簡単なJDBCストアド・プロシージャの公開
次のJavaクラスの実行可能ファイルがデータベースにロードされたとします。
import java.sql.*; import java.io.*; import oracle.jdbc.*; public class GenericDrop { public static void dropIt(String object_type, String object_name) throws SQLException { // Connect to Oracle using JDBC driver Connection conn = DriverManager.getConnection("jdbc:default:connection:"); // Build SQL statement String sql = "DROP " + object_type + " " + object_name; try { Statement stmt = conn.createStatement(); stmt.executeUpdate(sql); stmt.close(); } catch (SQLException e) { System.err.println(e.getMessage()); } } }
GenericDrop
クラスにはdropIt()
という名前の1つのメソッドがあり、このメソッドはあらゆる種類のスキーマ・オブジェクトを削除します。たとえば、引数table
およびemployees
をdropIt()
に渡すと、メソッドはデータベース表employees
をスキーマから削除します。
dropIt()
メソッドのコール仕様は次のとおりです。
CREATE OR REPLACE PROCEDURE drop_it (obj_type VARCHAR2, obj_name VARCHAR2) AS LANGUAGE JAVA NAME 'GenericDrop.dropIt(java.lang.String, java.lang.String)';
String
に対する参照は完全に修飾する必要があることに注意してください。java.lang
パッケージはJavaプログラムで自動的に使用できますが、コール仕様で明示的に名前を付ける必要があります。
例6-2 main()メソッドの公開
通常、Java名とコール仕様パラメータは対応する必要があります。ただし、この規則はmain()
メソッドには適用されません。そのString[]
パラメータは、複数のCHAR
またはVARCHAR2
のコール仕様パラメータにマッピングできます。引数を表示する次のクラスのmain()
メソッドについて考えます。
public class EchoInput { public static void main (String[] args) { for (int i = 0; i < args.length; i++) System.out.println(args[i]); } }
main()
を公開するには、次のコール仕様を記述します。
CREATE OR REPLACE PROCEDURE echo_input(s1 VARCHAR2, s2 VARCHAR2, s3 VARCHAR2) AS LANGUAGE JAVA NAME 'EchoInput.main(java.lang.String[])';
コール仕様パラメータに制約(精度、サイズおよびNOT NULL
など)を課すことはできません。そのため、VARCHAR2
パラメータの最大サイズは指定できません。ただし、VARCHAR2
変数の最大サイズを次のように指定する必要があります。
DECLARE last_name VARCHAR2(20); -- size constraint required
例6-3 整数値を戻すメソッドの公開
次の例では、指定したデータベース表の行数を戻すrowCount()
メソッドが公開されます。
import java.sql.*; import java.io.*; import oracle.jdbc.*; public class RowCounter { public static int rowCount (String tabName) throws SQLException { Connection conn = DriverManager.getConnection("jdbc:default:connection:"); String sql = "SELECT COUNT(*) FROM " + tabName; int rows = 0; try { Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery(sql); while (rset.next()) { rows = rset.getInt(1); } rset.close(); stmt.close(); } catch (SQLException e) { System.err.println(e.getMessage()); } return rows; } }
コール仕様では、NUMBER
のサブタイプ(INTEGER
、REAL
およびPOSITIVE
など)が許可されていません。そのため、次のコール仕様では、戻り型はNUMBER
であり、INTEGER
ではありません。
CREATE FUNCTION row_count (tab_name VARCHAR2) RETURN NUMBER AS LANGUAGE JAVA NAME 'RowCounter.rowCount(java.lang.String) return int';
例6-4 引数の値を切り替えるメソッドの公開
引数の値を切り替える、次のSwapper
クラスのswap()
メソッドについて考えます。
public class Swapper { public static void swap (int[] x, int[] y) { int hold = x[0]; x[0] = y[0]; y[0] = hold; } }
コール仕様によって、swap()
メソッドがコール仕様swap()
として公開されます。値を渡して戻す必要があるため、このコール仕様ではIN OUT
仮パラメータが宣言されます。すべてのコール仕様のOUT
パラメータおよびIN OUT
パラメータを、Java配列パラメータにマッピングする必要があります。
CREATE PROCEDURE swap (x IN OUT NUMBER, y IN OUT NUMBER) AS LANGUAGE JAVA NAME 'Swapper.swap(int[], int[])';
ノート:
Javaメソッドとそのコール仕様には同じ名前を設定できます。