この付録では、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
インスタンスはデータベースではなくクライアントで作成されます。
set
XXX
メソッドを使用する場合、名前によるバインドはサポートされていません。特定の環境下では、以前のバージョンのOracle JDBCドライバは、set
XXX
メソッドの使用時にも名前によって文変数をバインドできました。次の文では、名前付き変数EmpId
が整数314159
とバインドされます。
PreparedStatement p = conn.prepareStatement ("SELECT name FROM emp WHERE id = :EmpId"); p.setInt(1, 314159);
この、set
XXX
メソッド使用時の名前によるバインド機能は、JDBC仕様にはありません。また、Oracleもこの機能をサポートしません。JDBCドライバでは、SQLException
または予期しない結果が発生します。Oracle Database 10g JDBCドライバから、名前によるバインドはset
XXX
AtName
メソッドの使用によってサポートされています。
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
が送られます。