ヘッダーをスキップ
Oracle Database JDBC開発者ガイドおよびリファレンス
11gリリース1(11.1)
E05720-02
  目次
目次
索引
索引

戻る
戻る
次へ
次へ
 

11 Oracleデータへのアクセスと操作

この章では、oracle.sql.*形式でのデータ・アクセスについて、標準Java形式と対比させて説明します。oracle.sql.*形式の使用には、結果セットおよび文を適宜OracleResultSetOracleStatementOraclePreparedStatementおよびOracleCallableStatementにキャストすること、およびこれらのクラスのgetOracleObjectsetOracleObjectgetXXXおよびsetXXXメソッド(XXXoracle.sqlパッケージの型に対応)を使用することが関係しています。

次の項目が含まれます。

データ型マッピング

Oracle JDBCドライバは、Oracle固有のデータ型に加えて、標準JDBC型をサポートしています。この項では、標準およびOracle固有のSQL-Javaデフォルト型マッピングについて説明します。この項では、次の項目について説明します。

マッピングの表

表11-1に、SQLデータ型、JDBC型コード、標準Java型およびOracle拡張型間のデフォルト・マッピングを示します。

SQLデータ型列には、Oracle Database 11gに存在するSQL型をリストします。JDBC型コード列には、JDBC標準によってサポートされ、java.sql.Typesクラス、またはoracle.jdbc.OracleTypesクラスでOracleによって定義されるデータの型コードをリストします。標準型の型コードは、この2つのクラスで同一です。

標準Java型列には、Java言語で定義される標準型をリストします。Oracle拡張機能Java型の列には、データベース内の各SQLデータ型に対応したoracle.sql.*Java型を示します。これらは、oracle.sql.* Java型でSQLデータすべての取出しを可能にするOracle拡張機能です。SQLデータをoracle.sql.*データ型として操作すると、変換が最小限になり、パフォーマンスが向上し、変換の無駄がなくなります。

表11-1 SQL型とJava型間のデフォルト・マッピング

SQLデータ型 JDBC型コード 標準Java型 Oracle拡張機能Java型

標準JDBC型:



CHAR

java.sql.Types.CHAR

java.lang.String

oracle.sql.CHAR

VARCHAR2

java.sql.Types.VARCHAR

java.lang.String

oracle.sql.CHAR

LONG

java.sql.Types.LONGVARCHAR

java.lang.String

oracle.sql.CHAR

NUMBER

java.sql.Types.NUMERIC

java.math.BigDecimal

oracle.sql.NUMBER

NUMBER

java.sql.Types.DECIMAL

java.math.BigDecimal

oracle.sql.NUMBER

NUMBER

java.sql.Types.BIT

boolean

oracle.sql.NUMBER

NUMBER

java.sql.Types.TINYINT

byte

oracle.sql.NUMBER

NUMBER

java.sql.Types.SMALLINT

short

oracle.sql.NUMBER

NUMBER

java.sql.Types.INTEGER

int

oracle.sql.NUMBER

NUMBER

java.sql.Types.BIGINT

long

oracle.sql.NUMBER

NUMBER

java.sql.Types.REAL

float

oracle.sql.NUMBER

NUMBER

java.sql.Types.FLOAT

double

oracle.sql.NUMBER

NUMBER

java.sql.Types.DOUBLE

double

oracle.sql.NUMBER

RAW

java.sql.Types.BINARY

byte[]

oracle.sql.RAW

RAW

java.sql.Types.VARBINARY

byte[]

oracle.sql.RAW

LONGRAW

java.sql.Types.LONGVARBINARY

byte[]

oracle.sql.RAW

DATE

java.sql.Types.DATE

java.sql.Date

oracle.sql.DATE

DATE

java.sql.Types.TIME

java.sql.Time

oracle.sql.DATE

TIMESTAMP

java.sql.Types.TIMESTAMP

javal.sql.Timestamp

oracle.sql.TIMESTAMP

BLOB

java.sql.Types.BLOB

java.sql.Blob

oracle.sql.BLOB

CLOB

java.sql.Types.CLOB

java.sql.Clob

oracle.sql.CLOB

ユーザー定義オブジェクト

java.sql.Types.STRUCT

java.sql.Struct

oracle.sql.STRUCT

ユーザー定義参照

java.sql.Types.REF

java.sql.Ref

oracle.sql.REF

ユーザー定義コレクション

java.sql.Types.ARRAY

java.sql.Array

oracle.sql.ARRAY

ROWID

java.sql.Types.ROWID

java.sql.RowId

oracle.sql.ROWID

NCLOB

java.sql.Types.NCLOB

java.sql.NClob

oracle.sql.NCLOB

NCHAR

java.sql.Types.NCHAR

java.lang.String

oracle.sql.CHAR


Oracle拡張機能:



BFILE

oracle.jdbc.OracleTypes.BFILE

N/A

oracle.sql.BFILE

REF CURSOR

oracle.jdbc.OracleTypes.CURSOR

java.sql.ResultSet

oracle.jdbc.OracleResultSet

TIMESTAMP

oracle.jdbc.OracleTypes.TIMESTAMP

java.sql.Timestamp

oracle.sql.TIMESTAMP

TIMESTAMP WITH TIME ZONE

oracle.jdbc.OracleTypes.TIMESTAMPLTZ

java.sql.Timestamp

oracle.sql.TIMESTAMPLTZ

TIMESTAMP WITH LOCAL TIME ZONE

oracle.jdbc.OracleTypes.TIMESTAMPLTZ

java.sql.Timestamp

oracle.sql.TIMESTAMPLTZ



注意:

バージョン8.1.7など、TIMESTAMPデータ型をサポートしていないデータベースのバージョンの場合、TIMESTAMPDATEにマップされます。

マッピングに関する注意

この項では、NUMBERおよびユーザー定義型のマッピングに関する詳細を提供します。

NUMBER型

Oracle NUMBER値が対応できる様々な型コードでは、マッピングを正しく動作させるために、データのサイズに適切なgetterルーチンをコールします。たとえば、-128 < x < 128の項目xに対してJava tinyint値を取得するには、getByteをコールします。

ユーザー定義型

オブジェクト、オブジェクト参照およびコレクションなどのユーザー定義型は、デフォルトでjava.sql.Structなどの弱いJava型にマップされますが、かわりに強い型指定のカスタムJavaクラスにもマップできます。カスタムJavaクラスは、次のいずれかのインタフェースを実装できます。

  • 標準java.sql.SQLData

  • Oracle固有oracle.sql.ORAData

データ変換での考慮事項

JDBCプログラムでSQLデータをJavaに取り込む場合は、標準Java型またはoracle.sqlパッケージの型を使用できます。この項には、次の項目が含まれます。

標準型とOracle型

oracle.sqlのOracleデータ型では、データベースで使用されているのと同じビット形式でデータが格納されます。Oracle Database 10gより前のバージョンのOracle JDBCドライバでは、通常、Oracleデータ型の方が効率性に優れていました。Oracle Database 10g JDBCドライバは大幅に更新されました。その結果、ほとんどの場合は、oracle.sqlのデータ型よりも標準Java型が優先されるようになりました。特に、java.lang.Stringは、効率性の面でoracle.sql.CHARよりもとても優れています。

一般的にはJava標準型の使用をお薦めします。例外として次のような場合があります。

  • OraDataの機能の方がニーズに合っている場合は、java.sql.SqlDataではなく、oracle.sql.OraDataを使用します。

  • 浮動小数点数の値を正確に保持する必要がある場合は、java.lang.Doubleではなくoracle.sql.NUMBERを使用します。Oracle NUMBERは10進表現ですが、Java DoubleおよびFloatは2進表現となります。ある形式から別の形式へ変換を行うと、その結果が実際の表現値から少し変動した値となる可能性があります。さらに、2つの形式では、表現できる値の範囲がそれぞれ異なります。

  • JDK 1.5以前のバージョンを使用している場合、または最大限のパフォーマンスを実現する必要がある場合は、java.sql.Dateまたはjava.sql.Timestampではなく、oracle.sql.DATEまたはoracle.sql.TIMESTAMPを使用します。また、多くの日付値を読み取る場合や、一握りのデータしか計算または表示しない場合にも、oracle.sqlデータ型を使用できます。JDK 1.6より前のすべてのバージョンでは、不具合によりjava.lang.Dateおよびjava.lang.Timestampオブジェクトの作成処理が遅くなるという問題があります(特に、マルチスレッド環境において)。この不具合は、JDK 1.6で修正されました。


注意:

oracle.sqlデータ型をJava標準データ型に変換した場合、oracle.sqlデータ型を使用する利点は失われます。

SQL NULLデータの変換

Javaは、SQL NULLデータを、Javaの値nullで表現します。Javaデータ型は、プリミティブ型(byteintfloatなど)とオブジェクト型(クラス・インスタンスなど)の2つのカテゴリに分類されます。プリミティブ型でNULLを表すことはできません。かわりに、JDBC仕様で定義されているように、nullを0(ゼロ)値として格納します。これは、結果の解釈時にあいまいさが生じる原因ともなります。

一方、Javaオブジェクト型はNULLを表現できます。Java言語は、nullを表現可能な各プリミティブ型に対応したオブジェクト・コンテナ型を定義します。オブジェクト・コンテナ型は、SQLデータがSQL NULLをあいまいさを残さずに検出するためのターゲットとして使用する必要があります。

NULLのテスト

関係演算子を使用してNULL値同士の比較、またはNULL値と他の値を比較することはできません。たとえば、次のSELECT文は、COMM列にNULL値が1つ以上存在する場合でも行を戻しません。

PreparedStatement pstmt = conn.prepareStatement(
  "SELECT * FROM EMP WHERE COMM = ?");
pstmt.setNull(1, java.sql.Types.VARCHAR);

次の例では、戻り値にNULLが含まれる可能性がある場合に値が等しいかどうかを比較する方法を示します。このコードは、COMMに値100が存在しない場合、EMP表からENAMESNULLとして戻します。

PreparedStatement pstmt = conn.prepareStatement("SELECT ENAME FROM EMP
  WHERE COMM =? OR  ((COMM IS NULL) AND (? IS NULL))");
pstmt.setBigDecimal(1, new BigDecimal(100));
pstmt.setNull(2, java.sql.Types.VARCHAR);

結果セットと文拡張要素

JDBC Statementオブジェクトは、java.sql.ResultSetとして型指定されたOracleResultSetオブジェクトを戻します。標準JDBCメソッドのみをオブジェクトに適用する場合は、オブジェクトのResultSet型を維持してください。ただし、オブジェクト上でOracle拡張機能を使用する場合は、Oracle拡張機能をOracleResultSetにキャストする必要があります。Oracleの結果セット拡張機能は、すべてoracle.jdbc.OracleResultSetインタフェースに含まれ、Statement拡張機能は、すべてoracle.jdbc.OracleStatementインタフェースに含まれています。

たとえば、標準Statementオブジェクトstmtがあり、標準JDBC ResultSetメソッドのみを使用する場合、次のように記述します。

ResultSet rs = stmt.executeQuery("SELECT * FROM emp");

JDBCに対するOracle拡張機能を使用する場合は、結果を標準ResultSet変数内に選択し、次にその変数をOracleResultSetにキャストします。

結果セット・クラスおよび文クラスへの主要拡張機能には、getOracleObjectおよびsetOracleObjectメソッドが含まれます。これらのメソッドは、oracle.sql.*形式でデータへのアクセスおよび操作を実行するために使用します。

Oracleのgetおよびsetメソッドと標準JDBCの比較

この項では、getおよびsetメソッド、特にJDBC標準getObjectsetObjectメソッドおよびOracle固有のgetOracleObjectsetOracleObjectメソッドについて説明します。また、oracle.sql.*形式のデータへのアクセス方法をJava形式と比較しながら説明します。

Oracle SQL型には、すべて、対応する特定のgetXXXメソッドがありますが、便宜上または簡素化の目的で、または受け取るデータの型が不明な場合は、一般的なgetメソッドを使用できます。

この項には、次の項目が含まれます。


注意:

表名を使用して列名を修飾し、その列名をパラメータとしてgetXXXメソッドに渡すことはできません。たとえば、次のようになります。
ResultSet rset = stmt.executeQuery("SELECT emp.deptno, dept.deptno FROM emp, dept");
rset.getInt("emp.deptno");

このコード例の場合、getIntメソッドで例外が発生します。getXXXメソッドで列を一意に識別するには、列索引を使用するか、または問合せで列別名を指定してその別名をgetXXXメソッドで使用します。


標準getObjectメソッド

結果セットまたはコール可能文の標準getObjectメソッドの戻り型は、java.lang.Objectです。戻されるオブジェクトのクラスは、次に示すようにSQL型に基づきます。

  • Oracle固有ではないSQLデータ型の場合、JDBC仕様のマッピングに従い、getObjectは列のSQL型に対応するデフォルトのJava型を戻します。

  • Oracle固有のデータ型の場合、getObjectは適切なoracle.sql.*クラス(oracle.sql.ROWIDなど)のオブジェクトを戻します。

  • Oracleデータベース・オブジェクトの場合、getObjectは、使用する型マップで指定されたクラスのJavaオブジェクトを戻します。型マップは、データベース型名からJavaクラスへのマッピングを指定します。getObject(parameter_index)メソッドでは、接続のデフォルト型マップを使用します。getObject(parameter_index, map)を使用すると、型マップを渡すことができます。型マップが特定のOracleオブジェクトのマッピングを提供しない場合、getObjectoracle.sql.STRUCTオブジェクトを戻します。

Oracle getOracleObjectメソッド

結果セットまたはコール可能文からデータをoracle.sql.*オブジェクトとして取り出す場合は、特殊なプロセスに従う必要があります。結果セットの場合は、結果セット自体をoracle.jdbc.OracleResultSetにキャストしてから、getObjectのかわりにgetOracleObjectをコールする必要があります。CallableStatementおよびoracle.jdbc.OracleCallableStatementにも同じことが適用されます。

getOracleObjectの戻り型はoracle.sql.Datumです。実際に戻されるオブジェクトは、該当するoracle.sql.*クラスのインスタンスです。メソッド・シグネチャは次のとおりです。

public oracle.sql.Datum getOracleObject(int parameter_index)

Datum変数内にデータを取り出した場合は、標準Java instanceof演算子を使用して、実際のoracle.sql.*型を決定します。

例: 結果セットでのgetOracleObjectの使用方法

次の例では、CHARデータの列を含む表およびBFILEロケータを含む列を作成します。SELECT文では、表の内容を結果セットとして取り出します。その後、getOracleObjectCHARデータをchar_datum変数に、BFILEロケータをbfile_datum変数に取り出します。getOracleObjectDatumオブジェクトを戻すため、戻り値をそれぞれ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へのコールを作成します。このプログラムは、SCOTTを準備済コールに渡し、DATE型を出力パラメータとして登録します。コールの実行後、getOracleObjectSCOTTに関連付けられている日付を取り出します。getOracleObjectDatumオブジェクトを戻すため、結果セットはDATEにキャストされる点に留意してください。

OracleCallableStatement cstmt = (OracleCallableStatement)conn.prepareCall
                                   ("begin myGetDate (?, ?); end;");

cstmt.setString (1, "SCOTT");
cstmt.registerOutParameter (2, Types.DATE);
cstmt.execute ();

DATE date = (DATE) ((OracleCallableStatement)cstmt).getOracleObject (2);
...

getObjectおよびgetOracleObject戻り型のまとめ

表11-2に、各Oracle SQL型のgetObjectメソッドとgetOracleObjectメソッドに対応した、基礎となる戻り型を示します。

ただし、これらのメソッドを使用する際は、次のことを念頭に置いてください。

  • getObjectは、データを常にjava.lang.Objectインスタンスに戻します。

  • getOracleObjectは、データを常にoracle.sql.Datumインスタンスに戻します。

いずれかの特殊機能を使用するには、戻されたオブジェクトをキャストする必要があります。

表11-2 getObjectおよびgetOracleObject戻り型

Oracle SQL型 getObjectの基礎となる戻り型 getOracleObjectの基礎となる戻り型

CHAR

String

oracle.sql.CHAR

VARCHAR2

String

oracle.sql.CHAR

NCHAR

String

oracle.sql.CHAR

LONG

String

oracle.sql.CHAR

NUMBER

java.math.BigDecimal

oracle.sql.NUMBER

RAW

byte[]

oracle.sql.RAW

LONGRAW

byte[]

oracle.sql.RAW

DATE

java.sql.Date

oracle.sql.DATE

TIMESTAMP

java.sql.Timestamp脚注 1 

oracle.sql.TIMESTAMP

TIMESTAMP WITH TIME ZONE

oracle.sql.TIMESTAMPLTZ

oracle.sql.TIMESTAMPLTZ

TIMESTAMP WITH LOCAL TIME ZONE

oracle.sql.TIMESTAMPLTZ

oracle.sql.TIMESTAMPLTZ

BINARY_FLOAT

java.lang.Float

oracle.sql.BINARY_FLOAT

BINARY_DOUBLE

java.lang.Double

oracle.sql.BINARY_DOUBLE

INTERVAL DAY TO SECOND

oracle.sql.INTERVALDS

oracle.sql.INTERVALDS

INTERVAL YEAR TO MONTH

oracle.sql.INTERVALYM

oracle.sql.INTERVALYM

ROWID

oracle.sql.ROWID

oracle.sql.ROWID

REF CURSOR

java.sql.ResultSet

(未サポート)

BLOB

oracle.sql.BLOB

oracle.sql.BLOB

CLOB

oracle.sql.CLOB

oracle.sql.CLOB

NCLOB

java.sql.NClob

oracle.sql.NCLOB

BFILE

oracle.sql.BFILE

oracle.sql.BFILE

Oracleオブジェクト

型マップで指定されたクラス

またはoracle.sql.STRUCT(型マップにエントリがない場合)

oracle.sql.STRUCT

Oracleオブジェクト参照

oracle.sql.REF

oracle.sql.REF

コレクション(VARRAYまたはNESTED TABLE)

oracle.sql.ARRAY

oracle.sql.ARRAY


脚注 1 ResultSet.getObjectは、oracle.jdbc.J2EE13Compliant接続プロパティがTRUEに設定されている場合のみjava.sql.Timestampを戻します。そうでない場合、このメソッドはoracle.sql.TIMESTAMPを戻します。


注意:

ResultSet.getObjectメソッドは、接続プロパティoracle.jdbc.J2EE13CompliantTRUEに設定されている場合のみ、TIMESTAMP SQL型のjava.sql.Timestampを戻します。このプロパティは、接続の取得時に設定する必要があります。この接続プロパティが設定されていない場合、または接続の取得後に設定した場合、ResultSet.getObjectメソッドはTIMESTAMP SQL型のoracle.sql.TIMESTAMPを戻します。

oracle.jdbc.J2EE13Compliant接続プロパティは、コードを変更せずに、次の方法で設定できます。

  • ojdbc5dms.jarファイルまたはojdbc6dms.jarファイルをCLASSPATHに含めます。これらのファイルでは、デフォルトでoracle.jdbc.J2EE13CompliantTRUEに設定されます。これらはOracle Application Serverリリースに固有のもので、一般のJDBCリリースには含まれていません。これらのファイルは$ORACLE_HOME/jdbc/libにあります。

  • javaコマンドをフラグ-Doracle.jdbc.J2EE13Compliant=trueを指定してコールし、システム・プロパティを設定します。たとえば、次のようになります。

    java -Doracle.jdbc.J2EE13Compliant=true ...
    

J2EE13CompliantTRUEに設定されると、動作はJDBC仕様の表B-3のようになります。



関連項目:

すべてのSQL型とJava型との型互換性については、表A-1「有効なSQLデータ型-Javaクラス・マッピング」を参照してください。

その他のgetXXXメソッド

標準JDBCでは、各標準Java型に対応したgetXXXgetBytegetIntgetFloatなど)が提供されます。これらの各メソッドは、そのメソッド名が意味する内容を正確に戻します。

さらに、OracleResultSetクラスとOracleCallableStatementクラスは、すべてのoracle.sql.*型に対応したgetXXXメソッドを完全に補完します。各getXXXメソッドは、oracle.sql.XXXオブジェクトを戻します。たとえば、getROWIDメソッドは、oracle.sql.ROWIDオブジェクトを戻します。

特定のgetXXXメソッドを使用してもパフォーマンス上の利点はありません。ただし、戻り型は戻されるオブジェクトに固有であるため、面倒なキャストの必要がなくなります。

この項には、次の項目が含まれます。

getXXXメソッドの戻り型

getXXXメソッドの戻り型と、Java Development Kit(JDK)1.6で指定するOracle拡張機能の詳細は、Javadocを参照してください。Oracle拡張機能のメソッドを使用するには、戻されたオブジェクトをOracleResultSetまたはOracleCallableStatementにキャストする必要があります。

getXXXメソッドに関する特別な注意

この項では、いくつかのgetXXXメソッドについて追加の詳細情報を示します。

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を戻します。

getObjectおよびgetXXXから戻されるオブジェクトのデータ型

getObjectの戻り型はjava.lang.Objectです。戻り型は、java.lang.Objectのサブクラスのインスタンスです。同様に、getOracleObjectの戻り型はoracle.sql.Datumで、戻り値のクラスはoracle.sql.Datumのサブクラスです。通常、適切なクラスの特定のメソッドおよび機能を使用するには、戻されたオブジェクトをそのクラスにキャストします。

また、汎用のgetObjectメソッドやgetOracleObjectメソッドのかわりに、特定のgetXXXメソッドも使用できます。getXXXの戻り型は、戻されるオブジェクトの型に対応しているため、getXXXメソッドを使用することにより、キャストを回避できます。たとえば、getCLOBの戻り型は、java.lang.Objectではなくoracle.sql.CLOBです。

戻り値のキャストの例

この例では、NUMBER型のデータを結果セットの最初の列としてフェッチしたものとします。NUMBERデータの精度を保持したまま操作するため、結果セットをOracleResultSetにキャストし、getOracleObjectを使用して、oracle.sql.*形式でNUMBERデータを戻します。結果セットをキャストしない場合は、getObjectを使用する必要があります。このメソッドは、数値データをJava Floatに戻すため、SQLデータの精度がいくらか失われます。

getOracleObjectメソッドは、出力がキャストされるまで、oracle.sql.NUMBERオブジェクトをoracle.sql.Datum戻り変数内に戻します。NUMBER戻り変数を使用し、そのクラスの特殊機能のいずれかを使用する場合は、getOracleObjectの出力をoracle.sql.NUMBERにキャストしてください。

NUMBER x = (NUMBER)ors.getOracleObject(1);

setObjectおよびsetOracleObjectメソッド

結果セットとコール可能文に標準getObjectとOracle固有のgetOracleObjectがあるように、OraclePreparedStatementOracleCallableStatementにも標準setObjectメソッドとOracle固有のsetOracleObjectメソッドがあります。setOracleObjectメソッドは、oracle.sql.*を入力パラメータとして取ります。

標準Java型をプリコンパイルされたSQL文またはコール可能文にバインドするには、setObjectメソッドを使用します。このメソッドはjava.lang.Objectを入力として取ります。setObjectメソッドはoracle.sql.*型のいくつかをサポートします。ただし、このメソッドの実装によって、BlobClobStructRefおよびArrayの各JDBC標準型に対応するoracle.sql.*クラスのインスタンスの入力が可能になります。

プリコンパイルされたSQL文またはコール可能文にoracle.sql.*型をバインドするには、setOracleObjectメソッドを使用します。このメソッドはoracle.sql.Datumのサブクラスを入力として取ります。setOracleObjectを使用するには、プリコンパイルされたSQL文またはコール可能文をOraclePreparedStatementまたはOracleCallableStatementにキャストする必要があります。

setObjectとsetOracleObjectの使用例

プリコンパイルされたSQL文には、charVal変数により提示されたoracle.sql.CHARデータがsetOracleObjectメソッドによってバインドされます。oracle.sql.*データをバインドするには、プリコンパイルされたSQL文をOraclePreparedStatementにキャストする必要があります。同様に、setObjectメソッドは、変数strValで表現されたJava Stringデータをバインドします。

PreparedStatement ps= conn.prepareStatement("text_of_prepared_statement");
((OraclePreparedStatement)ps).setOracleObject(1,charVal);
ps.setObject(2,strVal);

その他のsetXXXメソッド

getXXXメソッドの場合と同様、固有のsetXXXメソッドがいくつか存在します。標準setXXXメソッドは、標準Java型のバインド用に提供されます。また、Oracle固有のsetXXXメソッドは、Oracle固有の型のバインド用に提供されます。

同様に、setNullメソッドには次の2つの形式があります。

  • void setNull(int parameterIndex, int sqlType)

    これは、標準のjava.sql.PreparedStatementインタフェースで指定されるシグネチャです。このシグネチャは、java.sql.Typesまたはoracle.jdbc.OracleTypesクラスによって定義されるパラメータ索引とSQL型コードを取得します。REFARRAYまたはSTRUCT以外のオブジェクトをNULLに設定する場合は、このシグネチャを使用します。

  • void setNull(int parameterIndex, int sqlType, String sql_type_name)

    JDBC 2.0の場合、このシグネチャは標準のjava.sql.PreparedStatementインタフェースにも指定されます。このメソッドは、パラメータ索引およびSQL型コードに加え、SQL型名を取ります。このメソッドは、SQL型コードがjava.sql.Types.REFARRAYまたはSTRUCTの場合に使用します。型コードがREFARRAYまたはSTRUCT以外の場合、指定されたSQL型名は無視されます。

同様に、registerOutParameterメソッドには、REFARRAYまたはSTRUCTデータとともに使用するためのシグネチャがあります。

void registerOutParameter
            (int parameterIndex, int sqlType, String sql_type_name)

標準Java型のバインドのためのメソッドではなく、適切なsetXXXメソッドを使用してOracle固有型をバインドすると、多少パフォーマンスが向上することがあります。

この項には、次の項目が含まれます。

入力データのバインド

入力用のデータのバインド方法は3つあります。

  • データ自体をバインド・バッファに格納するダイレクト・バインド

  • データをストリーム処理するストリーム・バインド

  • テンポラリLOBを作成し、LOB APIを使用してデータをそのLOBに格納し、LOBロケータのバイトをバインド・バッファに格納するLOBバインド

3種類のバインドはパフォーマンスが異なり、バッチ処理に影響を与えます。ダイレクト・バインドは最も高速で、バッチ処理が正常に行われます。ストリーム・バインドはより低速で、複数のラウンドトリップが必要な場合があり、バッチ処理はオフになります。LOBバインドは非常に低速で、多数のラウンドトリップが必要です。バッチ処理は機能しますが、お薦めできません。これらのバインドでは、SQL文の型に応じてサイズの制限も異なります。

SQLパラメータについては、RAWVARCHAR2など標準のパラメータ型の長さはターゲット列のサイズによって固定されます。PL/SQLパラメータについては、サイズは32766という固定バイト数に制限されます。

Oracle Database 10gリリース2(10.2)では、PreparedStatementsetStringsetCharacterStreamsetAsciiStreamsetBytesおよびsetBinaryStreamメソッドが一部変更されています。APIの当初の動作は次のとおりでした。

  • setString: キャラクタのダイレクト・バインド

  • setCharacterStream: キャラクタのストリーム・バインド

  • setAsciiStream: バイトのストリーム・バインド

  • setBytes: バイトのダイレクト・バインド

  • setBinaryStream: バイトのストリーム・バインド

Oracle Database 10gリリース2(10.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文に埋め込まれている場合、バインド処理は異なります。詳細は、「LOBのデータ・インタフェース」を参照してください。

サーバー側内部ドライバには、他にも次の制限事項があります。

  • データ・サイズの文字数が4000バイトを超える場合、setStringsetCharacterStreamおよびsetASCIIStreamの各APIはSQL CLOB列ではサポートされていません。

  • データ・サイズが2000バイトを超える場合、setBytesおよびsetBinaryStreamの各APIはSQL BLOB列ではサポートされていません。


重要:

サーバー側内部ドライバでこれらのAPIを使用する場合は、クライアント・コードのデータ・サイズを入念にチェックしてください。


関連項目:

詳細な説明および考えられる対応策は、JDBCのリリース・ノートを参照してください。

WHERE句にCHARデータをバインドするためのメソッドsetFixedCHAR

データベース内のCHARデータは、列幅まで埋め込まれます。このため、SELECT文のWHERE句に文字データをバインドするためのsetCHARメソッドの使用に関して、制限が生じます。WHERE句の文字データも、SELECT文で合致させるために、列幅まで埋め込む必要があります。これは特に列幅がわからない場合に問題になります。

これを修正するために、OracleはOraclePreparedStatementクラスにsetFixedCHARメソッドを追加しました。このメソッドは埋込みなしの比較を実行します。


注意:

  • setFixedCHARメソッドを使用するには、必ずプリコンパイルされたSQL文オブジェクトを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;
 }

結果セット・メタデータ拡張要素の使用方法

oracle.jdbc.OracleResultSetMetaDataインタフェースはJDBC 2.0に準拠していますが、Oracle Database 10gによってサポートされていないため、getSchemaNameメソッドとgetTableNameメソッドは実装されません。

次のコードは、OracleResultSetMetadataインタフェースのメソッドをいくつか使用して、EMP表から列数を取り出し、各列の数値型とSQL型名を取り出します。

DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rset = dbmd.getTables("", "SCOTT", "EMP", 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

SQL CALL文とCALL INTO文の使用

CALL文を使用してSQL内からルーチンを実行できます。


注意:

ルーチンとは、スタンドアロンのプロシージャまたは関数や、型またはパッケージ内で定義されているプロシージャまたは関数です。スタンドアロンのルーチン上、またはルーチンが定義されている型やパッケージ上で、EXECUTE権限を持っている必要があります。CALL文の使用方法の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

ルーチンは、次の2つの方法で実行できます。

ルーチンが引数を取る場合は、引数を指定できます。引数には、位置表記、名前表記または混合表記を使用できます。

CALL INTO文

INTO句は関数のコールにのみ適用されます。この句には次の型の変数を使用できます。

PL/SQLブロック

PL/SQLの基本単位はブロックです。PL/SQLプログラムはすべてブロックで構成されています。ブロックは相互にネストできます。PL/SQLブロックには、宣言部、実行部、例外処理部の3つの部分があります。アプリケーションでPL/SQLブロックを使用すると、次のような利点があります。