この付録では、Java Database Connectivity(JDBC)リファレンス詳細情報について説明します。次の項目が含まれます。
表11-1は、Oracle JDBCドライバでサポートされているJavaクラスとSQLデータ型とのデフォルトのマッピングです。表11-1のJDBC型コード、標準Java型およびSQLデータ型の列の内容と、表A-1の内容を比較してください。
表A-1は、特定のSQLデータ型のマッピング先として有効な、すべてのJava型のリストです。Oracle JDBCドライバでは、これらの非デフォルト・マッピングをサポートしています。たとえば、SQL CHARデータをoracle.sql.CHARオブジェクトとしてインスタンス化するには、getCHARメソッドを使用します。java.math.BigDecimalオブジェクトとしてインスタンス化するには、getBigDecimalメソッドを使用します。
表A-1 有効なSQLデータ型-Javaクラス・マッピング
| SQLデータ型 | 実現可能なJava型 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
オブジェクト型 |
|
|
|
|
|
|
|
|
|
|
|
参照型 |
|
|
|
|
|
|
|
|
NESTED TABLE型および |
|
|
|
|
|
|
|
注意:
|
この項の表は、SQLとPL/SQLのデータ型、およびOracle JDBCドライバがこれらのデータ型をサポートしているかどうかのリストです。表A-2は、SQLデータ型に対するOracle JDBCドライバのサポート状況のリストです。
表A-2 SQLデータ型に対するサポート
| SQLデータ型 | JDBCドライバによるサポート |
|---|---|
|
BFILE |
可 |
|
BLOB |
可 |
|
CHAR |
可 |
|
CLOB |
可 |
|
DATE |
可 |
|
NCHAR |
不可(「注意」を参照) |
|
NCHAR VARYING |
不可 |
|
NUMBER |
可 |
|
NVARCHAR2 |
不可(「注意」を参照) |
|
RAW |
可 |
|
REF |
可 |
|
ROWID |
可 |
|
UROWID |
不可 |
|
VARCHAR2 |
可 |
|
注意: NCHAR型およびNVARCHAR2型は間接的にサポートされています。対応するjava.sql.Types型はありませんが、アプリケーションがformOfUse(NCHAR)をコールする場合には、これらの型にアクセスできます。 |
表A-3は、ANSIでサポートされているSQLデータ型に対するOracle JDBCドライバのサポート状況のリストです。
表A-3 ANSI-92 SQLデータ型に対するサポート
| ANSIでサポートされているSQLデータ型 | JDBCドライバによるサポート |
|---|---|
|
CHARACTER |
可 |
|
DEC |
可 |
|
DECIMAL |
可 |
|
DOUBLE PRECISION |
可 |
|
FLOAT |
可 |
|
INT |
可 |
|
INTEGER |
可 |
|
NATIONAL CHARACTER |
不可 |
|
NATIONAL CHARACTER VARYING |
不可 |
|
NATIONAL CHAR |
可 |
|
NATIONAL CHAR VARYING |
不可 |
|
NCHAR |
可 |
|
NCHAR VARYING |
不可 |
|
NUMERIC |
可 |
|
REAL |
可 |
|
SMALLINT |
可 |
|
VARCHAR |
可 |
表A-4は、SQLユーザー定義型に対するOracle JDBCドライバのサポート状況のリストです。
表A-4 SQLユーザー定義型に対するサポート
| SQLユーザー定義型 | JDBCドライバによるサポート |
|---|---|
|
OPAQUE |
可 |
|
参照型 |
可 |
|
オブジェクト型( |
可 |
|
NESTED TABLE型およびVARRAY型 |
可 |
表A-5は、PL/SQLデータ型に対するOracle JDBCドライバのサポート状況のリストです。PL/SQLデータ型には、次のカテゴリがあります。
スカラー型
スカラー文字列型(BOOLEANおよびDATEデータ型を含みます。)
コンポジット型
参照型
ラージ・オブジェクト(LOB)型
表A-5 PL/SQLデータ型に対するサポート
| PL/SQLデータ型 | JDBCドライバによるサポート |
|---|---|
|
スカラー型 |
|
|
BINARY INTEGER |
可 |
|
DEC |
可 |
|
DECIMAL |
可 |
|
DOUBLE PRECISION |
可 |
|
FLOAT |
可 |
|
INT |
可 |
|
INTEGER |
可 |
|
NATURAL |
可 |
|
NATURALn |
不可 |
|
NUMBER |
可 |
|
NUMERIC |
可 |
|
PLS_INTEGER |
可 |
|
POSITIVE |
可 |
|
POSITIVEn |
不可 |
|
REAL |
可 |
|
SIGNTYPE |
可 |
|
SMALLINT |
可 |
|
スカラー文字列型 |
|
|
CHAR |
可 |
|
CHARACTER |
可 |
|
LONG |
可 |
|
LONG RAW |
可 |
|
NCHAR |
不可(「注意」を参照) |
|
NVARCHAR2 |
不可(「注意」を参照) |
|
RAW |
可 |
|
ROWID |
可 |
|
STRING |
可 |
|
UROWID |
不可 |
|
VARCHAR |
可 |
|
VARCHAR2 |
可 |
|
BOOLEAN |
可 |
|
DATE |
可 |
|
コンポジット型 |
|
|
RECORD |
不可 |
|
TABLE |
不可 |
|
VARRAY |
可 |
|
参照型 |
|
|
REF CURSOR型 |
可 |
|
オブジェクト参照型 |
可 |
|
LOB型 |
|
|
BFILE |
可 |
|
BLOB |
可 |
|
CLOB |
可 |
|
NCLOB |
可 |
|
注意:
|
Oracle JDBCドライバは、いくつかの埋込みSQL92構文(中カッコで囲んで指定する構文)をサポートしています。現在のサポートは初歩的なものです。この項では、OracleのJDBCドライバによって提供される次のSQL92構文のサポートについて説明します。
ドライバのサポートが制限されている場合、これらの項では、選択可能な回避策についても説明します。
エスケープ処理の無効化
SQL92構文のエスケープ処理は、デフォルトで有効です。そのため、JDBCドライバは、SQLコードをデータベースに送信する前にエスケープ置換を実行します。通常のOracle SQL構文をドライバで使用するには、次の文を使用します。このようにすると、SQL92構文とエスケープ処理を使用するよりも効率がよくなります。
stmt.setEscapeProcessing(false);
日付、時刻およびタイムスタンプのリテラルに使用する構文は、データベースによって異なります。JDBCでは、特定の形式で記述された日付および時刻のみがサポートされています。この項では、SQL文内で使用する必要のある日付、時刻およびタイムスタンプのリテラルについて説明します。
JDBCドライバは、次の形式で記述されたSQL文内の日付リテラルをサポートしています。
{d 'yyyy-mm-dd'}
yyyy-mm-ddは、年、月および日を表します。たとえば、次のようになります。
{d '1995-10-22'}
JDBCドライバは、このエスケープ句を等価のOracleの表現「22 OCT 1995」に置換します。
次のコードの抜粋には、SQL文内での日付リテラルの使用例が含まれています。
// Connect to the database
// You can put a database name after the @ sign in the connection URL.
OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:oci:@");
ods.setUser("scott");
ods.setPassword("tiger");
Connection conn = ods.getConnection();
// Create a Statement
Statement stmt = conn.createStatement ();
// Select the ename column from the emp table where the hiredate is Jan-23-1982
ResultSet rset = stmt.executeQuery
("SELECT ename FROM emp WHERE hiredate = {d '1982-01-23'}");
// Iterate through the result and print the employee names
while (rset.next ())
System.out.println (rset.getString (1));
JDBCドライバは、次の形式で記述されたSQL文内の時刻リテラルをサポートしています。
{t 'hh:mm:ss'}
hh:mm:ssは、時、分および秒を表します。たとえば、次のようになります。
{t '05:10:45'}
JDBCドライバは、このエスケープ句を等価のOracleの表現「05:10:45」に置換します。
次のように時刻が指定されているとします。
{t '14:20:50'}
サーバーが24時間制のクロックを使用しているとすれば、等価のOracleの表現は「14:20:50」になります。
次のコードの抜粋には、SQL文内での時刻リテラルの使用例が含まれています。
ResultSet rset = stmt.executeQuery
("SELECT ename FROM emp WHERE hiredate = {t '12:00:00'}");
JDBCドライバは、次の形式で記述されたSQL文内のタイムスタンプ・リテラルをサポートしています。
{ts 'yyyy-mm-dd hh:mm:ss.f...'}
yyyy-mm-dd hh:mm:ss.f...は、年、月、日、時、分および秒を表します。端数秒の部分(.f...)は省略できます。たとえば、{ts '1997-11-01 13:22:45'}は、Oracle形式ではNOV 01 1997 13:22:45と表されます。
次のコードの抜粋には、SQL文内でのタイムスタンプ・リテラルの使用例が含まれています。
ResultSet rset = stmt.executeQuery
("SELECT ename FROM emp WHERE hiredate = {ts '1982-01-23 12:00:00'}");
Oracleオブジェクト型からSQL DATEデータ型へのマッピング
Oracle Database 8i以下のバージョンではTIMESTAMPデータがサポートされていませんでしたが、SQL標準への拡張機能として、Oracle DATEデータに時刻コンポーネントが含まれていました。このため、Oracle Database 8i以下のバージョンのJDBCドライバは、oracle.sql.DATEをjava.sql.Timestampにマップして時刻コンポーネントを保持していました。Oracle Database 9.0.1以上ではTIMESTAMPがサポートされ、9iのJDBCドライバがoracle.sql.DATEをjava.sql.Dateにマッピングするようになりました。このマッピングはOracle DATEデータの時刻コンポーネントを切り捨てたため、不正確でした。この問題を克服するために、Oracle Database 11.1では新しいフラグmapDateToTimestampが導入されました。このフラグのデフォルト値はtrueです。これは、デフォルトで、ドライバがoracle.sql.DATEをjava.sql.Timestampに正確にマップして時刻情報を保持することを意味します。不正確でも10gと互換性のあるoracle.sql.DATEからjava.sql.Dateへのマッピングが必要な場合は、mapDateToTimestampフラグの値をfalseに設定します。
|
注意: oracle.sql.DATEからjava.sql.Dateへのマッピングの問題を克服するために、Oracle Database 9.2でフラグV8Compatibleが導入されました。このフラグのデフォルト値はfalseで、これはOracle DATEデータのjava.sql.Dateデータへのマッピングが許可されることを意味します。ただし、このフラグの値をtrueに設定することによって、ユーザーはOracle DATEデータの時刻コンポーネントを保持することができました。このフラグは11gでは非推奨です。これは、Oracle Database 8iとの互換性がサポートされなくなったためです。 |
Oracle JDBCドライバでサポートしていないスカラー関数もあります。ドライバがサポートする関数を調べるには、Oracle固有のoracle.jdbc.OracleDatabaseMetaDataクラスおよび標準Javaのjava.sql.DatabaseMetadataインタフェースでサポートされている次のメソッドを使用します。
ドライバによってサポートされている数値演算関数をカンマで区切られたリストで戻します。たとえば、「ABS, COS, SQRT」です。
ドライバによってサポートされている文字列関数をカンマで区切られたリストで戻します。たとえば、「ASCII, LOCATE」です。
ドライバによってサポートされているシステム関数をカンマで区切られたリストで戻します。たとえば、「DATABASE, USER」です。
ドライバによってサポートされている時刻および日付関数をカンマで区切られたリストで戻します。たとえば、「CURDATE, DAYOFYEAR, HOUR」です。
|
注意: Oracle JDBCドライバは、ファンクション・キーワードのfnをサポートしています。 |
SQL LIKE句では、文字%および_には特別な意味があります。%は0文字以上の一致、_は1文字のみの一致に使用します。これらの文字を文字列内で文字どおりに使用する場合は、その前に特別なエスケープ文字を置きます。たとえば、アンパサンド&をエスケープ文字として使用する場合は、SQL文内では次のように識別させます。
Statement stmt = conn.createStatement ();
// Select the empno column from the emp table where the ename starts with '_'
ResultSet rset = stmt.executeQuery
("SELECT empno FROM emp WHERE ename LIKE '&_%' {ESCAPE '&'}");
// Iterate through the result and print the employee numbers
while (rset.next ())
System.out.println (rset.getString (1));
|
注意: 円記号(\)をエスケープ文字として使用する場合は、2回入力する(\\とする)必要があります。たとえば、次のようになります。
|
OracleのJDBCドライバは、外部結合構文をサポートしていません。回避策は、Oracle外部結合構文を使用することです。
次の構文のかわりに、
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery
("SELECT ename, dname
FROM {OJ dept LEFT OUTER JOIN emp ON dept.deptno = emp.deptno}
ORDER BY ename");
Oracle SQL構文を使用します。
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery
("SELECT ename, dname
FROM emp b, dept a WHERE a.deptno = b.deptno(+)
ORDER BY ename");
Oracle JDBCドライバは、次のプロシージャおよびファンクション・コール構文をサポートしています。
プロシージャ・コール:
{ call procedure_name (argument1, argument2,...) }
ファンクション・コール:
{ ? = call procedure_name (argument1, argument2,...) }
SQL92を標準SQL構文に変換する簡単なプログラムを記述できます。次のプログラムは、ファンクション・コール、日付リテラル、時刻リテラルおよびタイムスタンプ・リテラルのためのSQL92の文に対して、それに対応するSQL構文を出力します。このプログラムでは、oracle.jdbc.OracleSqlクラスのparse()メソッドで変換します。
public class Foo
{
static oracle.jdbc.OracleDriver driver = new oracle.jdbc.OracleDriver();
public static void main (String args[]) throws Exception
{
show ("{call foo(?, ?)}");
show ("{? = call bar (?, ?)}");
show ("{d '1998-10-22'}");
show ("{t '16:22:34'}");
show ("{ts '1998-10-22 16:22:34'}");
}
public static void show (String s) throws Exception
{
System.out.println (s + " => " +
driver.processSqlEscapes(s));
}
}
対応するSQL構文の出力です。
{call foo(?, ?)} => BEGIN foo(:1, :2); END;
{? = call bar (?, ?)} => BEGIN :1 := bar (:2, :3); END;
{d '1998-10-22'} => TO_DATE ('1998-10-22', 'YYYY-MM-DD')
{t '16:22:34'} => TO_DATE ('16:22:34', 'HH24:MI:SS')
{ts '1998-10-22 16:22:34'} => TO_TIMESTAMP ('1998-10-22 16:22:34', 'YYYY-MM-DD
HH24:MI:SS.FF')
Oracle JDBC実装には次の制限事項があります。しかし、これらすべての制限は、それほど重要でないか、あるいは容易に回避できます。この項には、次の項目が含まれます。
Oracle JDBCドライバではget getCursorNameおよびsetCursorNameメソッドはサポートされません。これらのメソッドをOracle構造体へマップする簡単な方法がないためです。かわりにROWIDの使用をお薦めします。
Oracle JDBCドライバでは、PL/SQLのRECORD、BOOLEAN、またはスカラー以外の要素型を持つ表の引数コールまたは戻り値をサポートできません。ただし、Oracle JDBCドライバはスカラー要素型のPL/SQL索引付き表をサポートします。
PL/SQLのRECORD、BOOLEAN、またはスカラー以外の表タイプの回避策として、データをJDBCによりサポートされる型として処理するコンテナ・プロシージャを作成します。たとえば、PL/SQLのBOOLEANを使用するストアド・プロシージャをラップするには、JDBCから文字または数値を取って、元のプロシージャにBOOLEANとして渡すストアド・プロシージャを作成します。出力パラメータの場合、元のプロシージャからBOOLEAN引数を受け取り、CHARまたはNUMBERとしてJDBCに渡します。同様に、PL/SQLレコードを使用するストアド・プロシージャをラップするには、レコードを独立したコンポーネント(CHARやNUMBERなど)、または構造化オブジェクト型として処理するストアド・プロシージャを作成します。PL/SQL表を使用するストアド・プロシージャをラップするには、データをコンポーネントに分割するか、Oracleコレクション型を使用します。
Oracle NUMBER型の算術演算は、浮動小数演算に関してIEEE 754規格に準拠していません。このため、Oracleによる演算結果とJavaによる演算結果に小さな誤差が生じることがあります。
Oracleでは、10進数演算と互換性のある形式で数値を格納し、小数点以下38桁までの精度を保証しています。このため、0(ゼロ)、無限大の負数、無限大の正数を正確に表現できます。各正数に対して、同じ絶対値の負数も表せます。
10-30〜(1 – 10-38) * 10126を38桁の完全精度で表せます。
特定のDatabaseMetaDataメソッドによりcatalogパラメータが定義されます。このパラメータは、そのメソッドの選択条件の1つです。Oracleには複数カタログはありませんが、複数パッケージはあります。
java.sql.SQLWarningクラスから、データベース・アクセス警告についての情報が提供されます。通常、警告には、警告の説明および警告を識別するコードが含まれます。警告は、その原因になったメソッドをレポートするためにそのオブジェクトに自動的に関連付けられます。Oracle JDBCドライバでは、通常、SQLWarningがサポートされていません。例外的に、スクロール可能な結果セット操作はSQL警告を生成します。しかし、SQLWarningインスタンスはデータベースではなくクライアントで作成されます。
setXXXメソッドを使用する場合、名前によるバインドはサポートされていません。特定の環境下では、以前のバージョンのOracle JDBCドライバは、setXXXメソッドの使用時にも名前によって文変数をバインドできました。次の文では、名前付き変数EmpIdが整数314159とバインドされます。
PreparedStatement p = conn.prepareStatement
("SELECT name FROM emp WHERE id = :EmpId");
p.setInt(1, 314159);
この、setXXXメソッド使用時の名前によるバインド機能は、JDBC仕様にはありません。また、Oracleもこの機能をサポートしません。JDBCドライバでは、SQLExceptionまたは予期しない結果が発生します。Oracle Database 10g JDBCドライバから、名前によるバインドはsetXXXAtNameメソッドの使用によってサポートされています。
executeメソッドをコールするまで、ドライバはバインド値をコピーしません。このためexecuteメソッドをコールする前にバインド値を変更すると、バインド値が変更されることがあります。たとえば、次のコードを考えてみましょう。
PreparedStatement p; ....... Date d = new Date(1181676033917L); p.setDate(1, d); d.setTime(0); p.executeUpdate();
このコードはデータベースにDate(1181676033917L)でなくDate(0)を挿入します。これは、パフォーマンス上の理由でJDBCドライバ実装によりバインド値がコピーされていないためです。
バインド変数の保持
Oracle9i Databaseより前のOracle JDBCドライバでは、JDBC 1.0の仕様として、executeのコールをまたいでバインド値が保持されませんでした。Oracle9i Database以降のすべてのリリースでは、バインド値が保持されます。たとえば、次のようになります。
PreparedStatement p = conn.prepareStatement
("SELECT name FROM emp WHERE id = ? AND dept = ?");
p.setInt(1, 314159);
p.setString(2, "SALES");
ResultSet r1 = p.execute();
p.setInt(1, 425260);
ResultSet r2 = p.execute();
以前のバージョンでは、2番目の引数にバインドされる値がないため、2回目のexecuteコールでSQLExceptionが発生していました。Oracle Database 10gから、2番目の引数の文字列SALESへのバインドが保持され、2回目のexecuteにより正しい値が返されます。
保持されたバインド値がストリームの場合は、Oracle JDBCドライバではストリームをリセットしません。アプリケーション・コードによってストリームのリセット、再配置または変更が行われないかぎり、後続のexecuteのコールにより引数値としてNULLが送られます。