11 Oracleデータへのアクセスと操作
この章では、Oracle拡張機能(oracle.sql.*
形式)について説明し、標準Java形式(java.sql.*
)と比較します。Oracle拡張機能を使用するには、結果セットと文を適宜OracleResultSet
、OracleStatement
、OraclePreparedStatement
およびOracleCallableStatement
にキャストし、これらのクラスのgetOracleObject
、setOracleObject
、get
XXX
およびset
XXX
メソッド(XXX
はoracle.sql
パッケージの型に対応)を使用する必要があります。
11.1 データ型マッピング
Oracle JDBCドライバは、Oracle固有のデータ型に加えて、標準JDBC型をサポートしています。この項では、標準およびOracle固有のSQL-Javaデフォルト型マッピングについて説明します。この項では、次の項目について説明します。
11.1.1 マッピングの表
次の表は、SQLデータ型、JDBC型コード、標準Java型およびOracle拡張型間のデフォルト・マッピングを示しています。
SQLデータ型の列は、Oracle Database 12cリリース1 (12.1)に存在するSQL型を示しています。JDBC型コードの列は、JDBC標準によってサポートされ、java.sql.Types
クラス、またはoracle.jdbc.OracleTypes
クラスでOracleによって定義されるデータの型コードを示しています。標準の型コードの場合、コードはこの2つのクラスで同一です。
標準Java型の列は、Java言語で定義される標準型を示しています。Oracle拡張機能Java型の列は、データベース内の各SQLデータ型に対応したoracle.sql.*
Java型を示しています。これらは、oracle.sql.*
Java型でSQLデータすべての取出しを可能にするOracle拡張機能です。
ノート:
一般に、Oracle JDBCドライバは、標準JDBC型を使用してSQLデータを操作するように最適化されています。いくつかの特殊な例では、oracle.sql
パッケージで入手できるOracle拡張クラスを使用するのが有利な場合があります。しかし、できるかぎりOracle拡張機能ではなく標準JDBC型を使用することを強くお薦めします。
表11-1 SQL型とJava型間のデフォルト・マッピング
SQLデータ型 | JDBC型コード | 標準Java型 | Oracle拡張機能Java型 |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ユーザー定義オブジェクト |
|
|
|
ユーザー定義参照 |
|
|
|
ユーザー定義コレクション |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(Oracle拡張機能) |
なし |
|
|
(Oracle拡張機能) |
|
|
|
(Oracle拡張機能) |
|
|
|
(Oracle拡張機能) |
|
|
|
(Oracle拡張機能) |
|
|
脚注1
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.BLOB
クラスは非推奨となり、oracle.jdbc.OracleBlob
インタフェースに置き換えられています。
脚注2
Oracle Database 12cリリース1以降、oracle.sql.CLOB
クラスは非推奨となり、oracle.jdbc.OracleClob
インタフェースに置き換えられています。
脚注3
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.STRUCT
クラスは非推奨となり、oracle.jdbc.OracleStruct
インタフェースに置き換えられています。
脚注4
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.REF
クラスは非推奨となり、oracle.jdbc.OracleRef
インタフェースに置き換えられています。
脚注5
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.ARRAY
クラスは非推奨となり、oracle.jdbc.OracleArray
インタフェースに置き換えられています。
ノート:
バージョン8.1.7など、TIMESTAMP
データ型をサポートしていないデータベースのバージョンの場合、TIMESTAMP
はDATE
にマップされます。
11.1.2 マッピングに関するノート
この項では、NUMBER
およびユーザー定義型のマッピングに関する詳細を提供します。
NUMBER型
Oracle NUMBER
値が対応できる様々な型コードでは、マッピングを正しく動作させるために、データのサイズに適切なgetterルーチンをコールします。たとえば、-128 < x < 128の項目xに対してJava tinyint
値を取得するには、getByte
をコールします。
ユーザー定義型
オブジェクト、オブジェクト参照およびコレクションなどのユーザー定義型は、デフォルトでjava.sql.Struct
などの弱いJava型にマップされますが、かわりに強い型指定のカスタムJavaクラスにもマップできます。カスタムJavaクラスは、次のいずれかのインタフェースを実装できます。
-
標準
java.sql.SQLData
-
Oracle固有
oracle.jdbc.OracleData
11.2 データ変換での考慮事項
11.2.1 標準型とOracle型
oracle.sql
のOracleデータ型では、データベースで使用されているのと同じビット形式でデータが格納されます。Oracle Database 10gより前のバージョンのOracle JDBCドライバでは、通常、Oracleデータ型の方が効率的でした。Oracle Database 10g以降、JDBCドライバは大幅に更新されました。その結果、ほとんどの場合は、oracle.sql
のデータ型よりも標準Java型が優先されるようになりました。特に、java.lang.String
は、oracle.sql.CHAR
よりはるかに効率的です。
一般的にはJava標準型の使用をお薦めします。例外として次のような場合があります。
-
OracleData
の機能の方がニーズに合っている場合は、java.sql.SqlData
ではなく、oracle.jdbc.OracleData
を使用します。 -
浮動小数点数の値を正確に保持する必要がある場合は、
java.lang.Double
ではなくoracle.sql.NUMBER
を使用します。OracleNUMBER
は10進表現ですが、JavaDouble
およびFloat
は2進表現となります。ある形式から別の形式へ変換を行うと、実際の表現値が少し変化することがあります。さらに、2つの形式を使用して表現できる値の範囲が異なります。パフォーマンスが重大で、値を操作せずに、単に値の読取りや書込みを行う場合には、
java.math.BigDecimal
ではなく、oracle.sql.NUMBER
を使用します。 -
JDK 6より前のJDKバージョンを使用している場合は、
oracle.sql.DATE
またはoracle.sql.TIMESTAMP
を使用します。JDK 6以降のバージョンを使用している場合、java.sql.Date
またはjava.sql.Timestamp
を使用します。ノート:
JDK 6より前のすべてのバージョンでは、不具合により
java.lang.Date
およびjava.lang.Timestamp
オブジェクトの作成処理が遅くなるという問題があります(特に、マルチスレッド環境において)。この不具合は、JDK 6で修正されました。 -
Oracle文字セットによるコードで表されている外部ソースのデータがある場合にかぎり、
oracle.sql.CHAR
を使用します。それ以外の場合はすべて、java.lang.String
を使用します。 -
STRUCT
、ARRAY
、BLOB
、CLOB
、REF
およびROWID
はすべて、対応するJDBC標準インタフェース型の実装クラスです。したがって、JDBC標準型と同一のOracle拡張型を使用する利点はありません。 -
BFILE
、TIMESTAMPTZ
およびTIMESTAMPLTZ
には、JDBC標準での表現がありません。これらのOracle拡張機能は使用する必要があります。 -
他のすべての場合には、Oracle拡張機能ではなく、標準JDBC型を使用する必要があります。
ノート:
oracle.sql
データ型をJava標準データ型に変換した場合、oracle.sql
データ型を使用する利点は失われます。
11.2.2 SQL NULLデータの変換について
Javaは、SQL NULL
データを、Javaの値null
で表現します。Javaデータ型は、プリミティブ型(byte
、int
、float
など)とオブジェクト型(クラス・インスタンスなど)の2つのカテゴリに分類されます。プリミティブ型でNULL
を表すことはできません。かわりに、JDBC仕様で定義されているように、null
を0(ゼロ)値として格納します。これは、結果の解釈時にあいまいさが生じる原因ともなります。
一方、Javaオブジェクト型はNULL
を表現できます。Java言語は、null
を表現可能なプリミティブ型ごとに対応したオブジェクト・コンテナ型を定義します。オブジェクト・コンテナ型は、SQLデータがSQL NULL
を明確に検出するためのターゲットとして使用する必要があります。
11.2.3 NULLのテストについて
関係演算子を使用してNULL
値同士、または他の値との比較をすることはできません。たとえば、次のSELECT
文は、COMMISSION_PCT
列にNULL
値が1つ以上存在する場合でも行を戻しません。
PreparedStatement pstmt = conn.prepareStatement( "SELECT * FROM EMPLOYEES WHERE COMMISSION_PCT = ?"); pstmt.setNull(1, java.sql.Types.VARCHAR);
次の例では、戻り値にNULL
が含まれる可能性がある場合に値が等しいかどうかを比較する方法を示します。このコードは、COMM
に値205が存在しない場合、EMPLOYEES
表からFIRST_NAME
をNULL
として戻します。
PreparedStatement pstmt = conn.prepareStatement("SELECT FIRST_NAME FROM EMPLOYEES WHERE COMMISSION_PCT =? OR ((COMM IS NULL) AND (? IS NULL))"); pstmt.setBigDecimal(1, new BigDecimal(205)); pstmt.setNull(2, java.sql.Types.VARCHAR);
11.3 結果セットと文拡張機能
Statement
オブジェクトは、java.sql.ResultSet
を戻します。標準JDBCメソッドのみをオブジェクトに適用する場合は、オブジェクトのResultSet
型を維持してください。ただし、オブジェクト上でOracle拡張機能を使用する場合は、Oracle拡張機能をOracleResultSet
にキャストする必要があります。Oracleの結果セット拡張機能は、すべてoracle.jdbc.OracleResultSet
インタフェースに含まれ、Statement
拡張機能は、すべてoracle.jdbc.OracleStatement
インタフェースに含まれています。
たとえば、標準Statement
オブジェクトstmt
があり、標準JDBC ResultSet
メソッドのみを使用する場合、次のように記述します。
ResultSet rs = stmt.executeQuery("SELECT * FROM employees");
JDBCに対するOracle拡張機能を使用する場合は、結果を選択して標準ResultSet
変数に入れ、次にその変数をOracleResultSet
にキャストします。
結果セット・クラスおよび文クラスへの主な拡張機能には、getOracleObject
およびsetOracleObject
メソッドがあります。これらのメソッドは、oracle.sql.*
形式でデータへのアクセスおよび操作を実行するために使用します。
11.4 Oracleのgetおよびsetメソッドと標準JDBCの比較
この項では、get
メソッドとset
メソッド、特にJDBC標準のgetObject
メソッドとsetObject
メソッドおよびOracle固有のgetOracleObject
メソッドとsetOracleObject
メソッドについて説明します。また、oracle.sql.*
形式のデータへのアクセス方法をJava形式と比較しながら説明します。
すべてのOracle SQL型に標準のget
XXX
メソッドを使用できます。
この項の内容は次のとおりです。
ノート:
表名を使用して列名を修飾し、その列名をパラメータとしてget
XXX
メソッドに渡すことはできません。たとえば:
ResultSet rset = stmt.executeQuery("SELECT employees.department_id, department.department_id FROM employees, department"); rset.getInt("employees.department_id");
このコード例の場合、getInt
メソッドで例外が発生します。get
XXX
メソッドで列を一意に識別するには、列索引を使用するか、または問合せで列別名を指定してその別名をget
XXX
メソッドで使用します。
11.4.1 標準getObjectメソッド
結果セットまたはコール可能文の標準getObject
メソッドの戻り型は、java.lang.Object
です。戻されるオブジェクトのクラスは、次に示すようにSQL型に基づきます。
-
Oracle固有ではないSQLデータ型の場合、JDBC仕様のマッピングに従い、
getObject
メソッドは列のSQL型に対応するデフォルトのJava型を戻します。 -
Oracle固有のデータ型の場合、
getObject
は適切なoracle.sql.*
クラス(oracle.sql.ROWID
など)のオブジェクトを戻します。 -
Oracle Databaseオブジェクトの場合、
getObject
は、使用する型マップで指定されたクラスのJavaオブジェクトを戻します。型マップは、データベース型名からJavaクラスへのマッピングを指定します。getObject(
parameter_index
)
メソッドでは、接続のデフォルト型マップを使用します。getObject(
parameter_index
,
map
)
を使用すると、型マップを渡すことができます。型マップに特定のOracleオブジェクトに対応するマッピングがない場合、getObject
はoracle.sql.OracleStruct
オブジェクトを戻します。
11.4.2 Oracle getOracleObjectメソッド
結果セットまたはコール可能文からデータをoracle.sql.*
オブジェクトとして取り出す場合は、特殊なプロセスに従う必要があります。OracleResultSet
オブジェクトの場合、結果セットをoracle.jdbc.OracleResultSet
にキャストしてから、getObject
ではなく、getOracleObject
をコールする必要があります。CallableStatement
およびoracle.jdbc.OracleCallableStatement
にも同じことが当てはまります。
getOracleObject
の戻り型はoracle.sql.Datum
です。実際に戻されるオブジェクトは、該当するoracle.sql.*
クラスのインスタンスです。メソッド・シグネチャは次のとおりです。
public oracle.sql.Datum getOracleObject(int p
arameter_index)
Datum
変数に取り出したデータを入れると、標準Java instanceof
演算子を使用して、実際にどのoracle.sql.*
型であるかを確認できます。
例: 結果セットでのgetOracleObjectの使用方法
次の例では、CHAR
データの列を含む表およびBFILE
ロケータを含む列を作成します。SELECT
文では、表の内容を結果セットとして取り出します。その後、getOracleObject
で取り出したCHAR
データをchar_datum
変数に、BFILE
ロケータをbfile_datum
変数に入れます。getOracleObject
はDatum
オブジェクトを戻すため、戻り値をそれぞれCHAR
およびBFILE
にキャストする必要があります。
stmt.execute ("CREATE TABLE bfile_table (x VARCHAR2 (30), b BFILE)"); stmt.execute ("INSERT INTO bfile_table VALUES ('one', BFILENAME ('TEST_DIR', 'file1'))"); ResultSet rset = stmt.executeQuery ("SELECT * FROM bfile_table"); while (rset.next ()) { CHAR char_datum = (CHAR) ((OracleResultSet)rset).getOracleObject (1); BFILE bfile_datum = (BFILE) ((OracleResultSet)rset).getOracleObject (2); ... }
例: コール可能文でのgetOracleObjectの使用方法
次の例では、文字列を日付と関連付けるプロシージャmyGetDate
へのコールを作成します。このプログラムは、HR
を準備済コールに渡し、DATE
型を出力パラメータとして登録します。コールの実行後、getOracleObject
はHR
に関連付けられている日付を取り出します。getOracleObject
はDatum
オブジェクトを戻すため、結果はDATE
にキャストされる点に留意してください。
OracleCallableStatement cstmt = (OracleCallableStatement)conn.prepareCall ("begin myGetDate (?, ?); end;"); cstmt.setString (1, "HR"); cstmt.registerOutParameter (2, Types.DATE); cstmt.execute (); DATE date = (DATE) ((OracleCallableStatement)cstmt).getOracleObject (2); ...
11.4.3 getObjectおよびgetOracleObject戻り型のまとめ
次の表は、各Oracle SQL型のgetObject
メソッドとgetOracleObject
メソッドの、基礎となる戻り型を示しています。
ただし、これらのメソッドを使用する際は、次のことを念頭に置いてください。
-
getObject
は、データを常にjava.lang.Object
インスタンスで戻します。 -
getOracleObject
は、データを常にoracle.sql.Datum
インスタンスで戻します。
表11-2 getObjectとgetOracleObjectの戻り型
Oracle SQL型 | getObjectの基礎となる戻り型 | getOracleObjectの基礎となる戻り型 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(未サポート) |
|
|
|
|
|
|
|
|
|
|
|
|
Oracleオブジェクト |
型マップで指定されたクラス または |
|
Oracleオブジェクト参照 |
|
|
コレクション(VARRAYまたはNESTED TABLE) |
|
|
脚注6
ResultSet.getObject
は、oracle.jdbc.J2EE13Compliant
接続プロパティがTRUE
に設定されている場合のみjava.sql.Timestamp
を戻します。そうでない場合、このメソッドはoracle.sql.TIMESTAMP
を戻します。
脚注7
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.BLOB
クラスは非推奨となり、oracle.jdbc.OracleBlob
インタフェースに置き換えられています。
脚注8
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.CLOB
クラスは非推奨となり、oracle.jdbc.OracleClob
インタフェースに置き換えられています。
脚注9
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.STRUCT
クラスは非推奨となり、oracle.jdbc.OracleStruct
インタフェースに置き換えられています。
脚注10
Oracle Database 12cリリース1以降、oracle.sql.REF
クラスは非推奨となり、oracle.jdbc.OracleRef
インタフェースに置き換えられています。
脚注11
Oracle Database 12cリリース1以降、oracle.sql.ARRAY
クラスは非推奨となり、oracle.jdbc.OracleArray
インタフェースに置き換えられています。
ノート:
ResultSet.getObject
メソッドは、接続プロパティoracle.jdbc.J2EE13Compliant
がTRUE
に設定されている場合のみ、TIMESTAMP
SQL型のjava.sql.Timestamp
を戻します。このプロパティは、接続の取得時に設定する必要があります。この接続プロパティが設定されていない場合、または接続の取得後に設定した場合、ResultSet.getObject
メソッドはTIMESTAMP
SQL型のoracle.sql.TIMESTAMP
を戻します。
oracle.jdbc.J2EE13Compliant
接続プロパティは、コードを変更せずに、次の方法で設定できます。
-
ojdbc6dms.jar
ファイルまたはojdbc7dms.jar
ファイルをCLASSPATH
に含めます。これらのファイルでは、デフォルトでoracle.jdbc.J2EE13Compliant
がTRUE
に設定されます。これらはOracle Application Serverリリースに固有のもので、一般のJDBCリリースには含まれていません。これらのファイルは$ORACLE_HOME/jdbc/lib
にあります。 -
java
コマンドをフラグ-Doracle.jdbc.J2EE13Compliant=true
を指定してコールし、システム・プロパティを設定します。たとえば、java -Doracle.jdbc.J2EE13Compliant=true ...
J2EE13Compliant
がTRUE
に設定されると、動作はJDBC仕様の表B-3のようになります。
関連トピック
11.4.4 その他のgetXXXメソッド
標準JDBCでは、各標準Java型に対応したget
XXX
(getByte
、getInt
、getFloat
など)が提供されます。これらの各メソッドは、そのメソッド名が意味する内容を正確に戻します。
さらに、OracleResultSet
クラスとOracleCallableStatement
インタフェースは、すべてのoracle.sql.*
型に対応したget
XXX
メソッドを補完します。各get
XXX
メソッドは、oracle.sql.
XXX
オブジェクトを戻します。たとえば、getROWID
メソッドは、oracle.sql.ROWID
オブジェクトを戻します。
特定のget
XXX
メソッドを使用してもパフォーマンス上の利点はありません。ただし、戻り型は戻されるオブジェクトに固有であるため、面倒なキャストの必要がなくなります。
この項の内容は次のとおりです。
11.4.4.2 getXXXメソッドに関する特別なノート
この項では、いくつかのget
XXX
メソッドについて追加の詳細情報を示します。
getBigDecimal
JDBC 2.0では、getBigDecimal
メソッドのメソッド・シグネチャが単純になっています。以前の入力シグネチャは次のいずれかでした。
(int columnIndex, int scale) or (String columnName, int scale)
単純になった入力シグネチャは次のとおりです。
(int columnIndex) or (String columnName)
小数点の右にある数字の数を指定するために使用するscale
パラメータは不要になりました。Oracle JDBCドライバは、完全な精度で数値を取り出します。
getBoolean
BOOLEAN
データベース型が存在しないため、getBoolean
を使用すると必ずデータ型変換が実行されます。getBoolean
メソッドは数値用の列に対してのみサポートされます。このような列に対してgetBoolean
が適用されると、0(ゼロ)値はfalse
として、それ以外の値はtrue
として解釈されます。別の種類の列に適用された場合は、getBoolean
は例外java.lang.NumberFormatException
を戻します。
11.4.5 getObjectおよびgetXXXから戻されるオブジェクトのデータ型
getObject
の戻り型はjava.lang.Object
です。戻り型は、java.lang.Object
のサブクラスのインスタンスです。同様に、getOracleObject
の戻り型はoracle.sql.Datum
で、戻り値のクラスはoracle.sql.Datum
のサブクラスです。通常、適切なクラスの特定のメソッドおよび機能を使用するには、戻されたオブジェクトをそのクラスにキャストします。
また、汎用のgetObject
メソッドやgetOracleObject
メソッドのかわりに、特定のget
XXX
メソッドも使用できます。get
XXX
の戻り型は、戻されるオブジェクトの型に対応しているため、get
XXX
メソッドを使用することにより、キャストを回避できます。たとえば、getCLOB
の戻り型は、java.lang.Object
ではなくoracle.sql.CLOB
です。
戻り値のキャストの例
この例では、NUMBER
タイプのデータを結果セットの最初の列としてフェッチしていると想定しています。精度を下げずにNUMBER
データを操作する必要があるので、OracleResultSet
に結果セットをキャストし、getOracleObject
を使用して、NUMBER
データをoracle.sql.*
形式で戻します。結果セットをキャストしない場合は、getObject
を使用する必要があります。数値データがJava Float
に戻されるため、SQLデータの精度が多少下がります。
getOracleObject
メソッドは、出力をキャストしないかぎり、oracle.sql.NUMBER
オブジェクトをoracle.sql.Datum
戻り変数に戻します。NUMBER
戻り変数を使用し、そのクラスの特殊機能のいずれかを使用する場合は、getOracleObject
の出力をoracle.sql.NUMBER
にキャストしてください。
NUMBER x = (NUMBER)ors.getOracleObject(1);
11.4.6 setObjectメソッドとsetOracleObjectメソッド
結果セットとコール可能文に標準getObject
とOracle固有のgetOracleObject
があるように、OraclePreparedStatement
とOracleCallableStatement
にも標準setObject
メソッドとOracle固有のsetOracleObject
メソッドがあります。setOracleObject
メソッドは、oracle.sql.*
を入力パラメータとして取ります。
標準Java型をプリペアド文またはコール可能文にバインドするには、java.lang.Object
を入力にとるsetObject
メソッドを使用します。setObject
メソッドは、いくつかのoracle.sql.*
型をサポートします。ただしこのメソッドは、JDBC標準型Blob
、Clob
、Struct
、Ref
およびArray
に対応するoracle.sql.*
クラスのインスタンスを入力できるように実装されています。
oracle.sql.*
型をプリペアド文またはコール可能文にバインドするには、oracle.sql.Datum
のサブクラスを入力にとるsetOracleObject
メソッドを使用します。setOracleObject
を使用するには、プリペアド文またはコール可能文をOraclePreparedStatement
またはOracleCallableStatement
にキャストする必要があります。
setObjectとsetOracleObjectの使用例
プリペアド文には、charVal
変数により表現されたoracle.sql.CHAR
データがsetOracleObject
メソッドによってバインドされます。oracle.sql.*
データをバインドするには、プリペアド文をOraclePreparedStatement
にキャストする必要があります。同様に、setObject
メソッドは、変数strVal
で表現されたJava String
データをバインドします。
PreparedStatement ps= conn.prepareStatement("t
ext_of_prepared_statement");
((OraclePreparedStatement)ps).setOracleObject(1,charVal);
ps.setObject(2,strVal);
11.4.7 その他のsetXXXメソッド
get
XXX
メソッドと同様に、固有なset
XXX
メソッドもいくつかあります。標準のset
XXX
メソッドはJava型をバインドするために、Oracle固有のset
XXX
メソッドはOracle固有の型をバインドするために提供されています。
同様に、setNull
メソッドには次の2つの形式があります。
-
void setNull(int
parameterIndex,
int
sqlType
)
これは、標準の
java.sql.PreparedStatement
インタフェースで指定されるシグネチャです。このシグネチャは、java.sql.Types
クラスまたはoracle.jdbc.OracleTypes
クラスによって定義されるパラメータ索引とSQL型コードを取ります。REF
、ARRAY
またはSTRUCT
以外のオブジェクトをNULL
に設定する場合は、このシグネチャを使用します。 -
void setNull(int
parameterIndex
,int
sqlType
, String
sql_type_name
)JDBC 2.0の場合、このシグネチャは標準の
java.sql.PreparedStatement
インタフェースにも指定されます。このメソッドは、パラメータ索引およびSQL型コードに加え、SQL型名を取ります。このメソッドは、SQL型コードがjava.sql.Types.REF
、ARRAY
またはSTRUCT
の場合に使用します。型コードがREF
、ARRAY
またはSTRUCT
以外の場合、指定されたSQL型名は無視されます。
同様に、registerOutParameter
メソッドには、REF
、ARRAY
またはSTRUCT
データとともに使用するためのシグネチャがあります。
void registerOutParameter (int parameterIndex, int sqlType, String sql_type_name)
標準Java型のバインドのためのメソッドではなく、適切なsetXXX
メソッドを使用してOracle固有型をバインドすると、多少パフォーマンスが向上することがあります。
この項の内容は次のとおりです。
11.4.7.1 入力データのバインド
入力用のデータのバインド方法は3つあります。
-
データ自体をバインド・バッファに格納するダイレクト・バインド
-
データをストリーム処理するストリーム・バインド
-
一時LOBを作成し、LOB APIを使用してデータをそのLOBに格納し、LOBロケータのバイトをバインド・バッファに格納するLOBバインド
3種類のバインドはパフォーマンスが異なり、バッチ処理に影響を与えます。ダイレクト・バインドは最も高速で、バッチ処理が正常に行われます。ストリーム・バインドはより低速で、複数のラウンドトリップが必要な場合があり、バッチ処理はオフになります。LOBバインドは非常に低速で、多数のラウンドトリップが必要です。バッチ処理は機能しますが、お薦めできません。これらのバインドでは、SQL文の型に応じてサイズの制限も異なります。
SQLパラメータについては、RAW
やVARCHAR2
など標準のパラメータ型の長さはターゲット列のサイズによって固定されます。PL/SQLパラメータについては、サイズは32766という固定バイト数に制限されます。
Oracle Database 10gリリース2では、PreparedStatement
のsetString
、setCharacterStream
、setAsciiStream
、setBytes
およびsetBinaryStream
メソッドが一部変更されています。APIの当初の動作は次のとおりでした。
-
setString
: キャラクタのダイレクト・バインド -
setCharacterStream
: キャラクタのストリーム・バインド -
setAsciiStream
: バイトのストリーム・バインド -
setBytes
: バイトのダイレクト・バインド -
setBinaryStream
: バイトのストリーム・バインド
Oracle Database 10gリリース2以降、データ・サイズおよびSQL文の型に基づくバインド・モードの自動切替えがサポートされています。
setBytesおよびsetBinaryStream
SQLでは、サイズが2000以下の場合はダイレクト・バインド、2000を超える場合はストリーム・バインドが使用されます。
PL/SQLでは、サイズが32766以下の場合はダイレクト・バインド、32766を超える場合はLOBバインドが使用されます。
setString、setCharacterStreamおよびsetAsciiStream
SQLでは、Javaキャラクタが32766以下の場合はダイレクト・バインド、32766を超える場合はストリーム・バインドが使用されます。これは文字セットに依存しません。
PL/SQLでは、使用形式パラメータの設定に応じて、データベース文字セットまたは各国語文字セット内のキャラクタ・データのバイト・サイズに注意する必要があります。バイト長が32766未満のデータにはダイレクト・バインド、32766以上のデータにはLOBバインドが使用されます。
固定長文字セットについては、Javaキャラクタ・データの長さにバイト単位の固定文字サイズをかけた値を上限値と比較します。可変長文字セットについては、Javaキャラクタの長さに応じて、次の3つの場合があります。
-
文字長が32766を最大文字サイズで割った値よりも小さい場合は、ダイレクト・バインドが使用されます。
-
文字長が32766を最小文字サイズで割った値よりも大きい場合は、LOBバインドが使用されます。
-
文字長がその間であり、変換済バイトの実際の長さが32766未満の場合は、ダイレクト・バインドが使用され、それ以外の場合はLOBバインドが使用されます。
ノート:
PL/SQLプロシージャがSQL文に埋め込まれている場合、バインド処理は異なります。
サーバー側内部ドライバには、他にも次の制限事項があります。
-
データ・サイズの文字数が32767バイトを超える場合、
setString
、setCharacterStream
およびsetASCIIStream
の各APIはSQL CLOB列ではサポートされていません。 -
データ・サイズが32767バイトを超える場合、
setBytes
およびsetBinaryStream
の各APIはSQL BLOB列ではサポートされていません。
ノート:
サーバー側内部ドライバでこれらのAPIを使用する場合は、クライアント・コードのデータ・サイズを入念にチェックしてください。
関連トピック
関連項目:
詳細な説明および考えられる対応策は、JDBCのリリース・ノートを参照してください。
11.4.7.2 WHERE句にCHARデータをバインドするためのメソッドsetFixedCHAR
データベース内のCHAR
データは、列幅まで埋め込まれます。このため、SELECT
文のWHERE
句に文字データをバインドするためのsetCHAR
メソッドの使用に関して、制限が生じます。WHERE
句の文字データも、SELECT
文で合致させるために、列幅まで埋め込む必要があります。これは特に列幅がわからない場合に問題になります。
これを修正するために、OracleはOraclePreparedStatement
クラスにsetFixedCHAR
メソッドを追加しました。このメソッドは埋込みなしの比較を実行します。
ノート:
-
setFixedCHAR
メソッドを使用するには、必ずプリペアド文オブジェクトをOraclePreparedStatement
にキャストしてください。 -
INSERT
文で、setFixedCHAR
を使用する必要はありません。データベースは挿入時に、常にそのデータを列幅まで自動的に埋め込みます。
例
次の例では、setCHAR
メソッドとsetFixedCHAR
メソッドの違いを示します。
/* Schema is : create table my_table (col1 char(10)); insert into my_table values ('JDBC'); */ PreparedStatement pstmt = conn.prepareStatement ("select count(*) from my_table where col1 = ?"); pstmt.setString (1, "JDBC"); // Set the Bind Value runQuery (pstmt); // This will print " No of rows are 0" CHAR ch = new CHAR("JDBC ", null); ((OraclePreparedStatement)pstmt).setCHAR(1, ch); // Pad it to 10 bytes runQuery (pstmt); // This will print "No of rows are 1" ((OraclePreparedStatement)pstmt).setFixedCHAR(1, "JDBC"); runQuery (pstmt); // This will print "No of rows are 1" void runQuery (PreparedStatement ps) { // Run the Query ResultSet rs = pstmt.executeQuery (); while (rs.next()) System.out.println("No of rows are " + rs.getInt(1)); rs.close(); rs = null; }
11.5 結果セット・メタデータ拡張機能の使用方法
oracle.jdbc.OracleResultSetMetaData
インタフェースはJDBC 2.0に準拠していますが、Oracle Databaseによってサポートされていないため、getSchemaName
メソッドとgetTableName
メソッドは実装されません。
次のコードは、OracleResultSetMetadata
インタフェースのメソッドをいくつか使用して、EMPLOYEES
表から列数を取り出し、各列の数値型とSQL型名を取り出します。
DatabaseMetaData dbmd = conn.getMetaData(); ResultSet rset = dbmd.getTables("", "HR", "EMPLOYEES", null); while (rset.next()) { OracleResultSetMetaData orsmd = ((OracleResultSet)rset).getMetaData(); int numColumns = orsmd.getColumnCount(); System.out.println("Num of columns = " + numColumns); for (int i=0; i<numColumns; i++) { System.out.print ("Column Name=" + orsmd.getColumnName (i+1)); System.out.print (" Type=" + orsmd.getColumnType (i + 1) ); System.out.println (" Type Name=" + orsmd.getColumnTypeName (i + 1)); } }
このプログラムは次の出力を戻します。
Num of columns = 5 Column Name=TABLE_CAT Type=12 Type Name=VARCHAR2 Column Name=TABLE_SCHEM Type=12 Type Name=VARCHAR2 Column Name=TABLE_NAME Type=12 Type Name=VARCHAR2 Column Name=TABLE_TYPE Type=12 Type Name=VARCHAR2 Column Name=TABLE_REMARKS Type=12 Type Name=VARCHAR2
11.6 SQL CALL文とCALL INTO文の使用について
次の2つの方法で、CALL文を使用してSQL内からルーチンを実行できます。
ノート:
ルーチンとは、スタンドアロンのプロシージャまたは関数や、型またはパッケージ内で定義されているプロシージャまたは関数です。スタンドアロンのルーチン上、またはルーチンが定義されている型やパッケージ上で、EXECUTE
権限を持っている必要があります。
-
コールをルーチン自身に名前で送信するか、
routine_clause
を使用します。 -
式の型の内部で
object_access_expression
を使用します。
ルーチンが引数を取る場合は、引数を指定できます。引数には、位置表記、名前表記または混合表記を使用できます。
CALL INTO文
INTO
句は関数のコールにのみ適用されます。この句には次の型の変数を使用できます。
-
ホスト変数
-
標識変数
関連項目:
詳細は、『Oracle Database SQL言語リファレンス』を参照してください
PL/SQLブロック
PL/SQLの基本単位は、ブロックです。すべてのPL/SQLプログラムはブロックで構成されており、ブロックは互いの内部にネストすることができます。PL/SQLブロックには、宣言部、実行部、例外処理部の3つの部分があります。アプリケーションでPL/SQLブロックを使用すると、次の利点があります。
-
パフォーマンスの向上
-
生産性の向上
-
完全な移植性
-
Oracleとの密接な統合
-
厳重なセキュリティ