- Oracle Developer Tools for Visual Studio の Visual Studio 2013 対応 は12.1.0.1.2(12cR2)から
- EntityFramework は 5 までしか使えず、6 だと対応していないというエラーが出る
-
ODAC 12c Release 3 からNuGetで公式から配布されるようになった
ODACの11g、12cにはOracle.ManagedDataAccessというのが追加されており、ネイティブコードが無くなったのでサーバー環境へのデプロイ時にODP.NETやOracleClientのインストールが不要になる!ということで、やり方を調べてみたメモ。
これのBのパターンでうまく行った。
- WCFサービスのホストプロジェクトなどDB接続が必要になるプロジェクトの参照にEntityFramewrokとOracle.ManagedDataAccessを追加し、ローカルコピーをTrueに
- Web.config/App.configを以下のように設定
[/xml]
- 適当にデプロイ
Oracle.ManagedDataAccessDTC.dll が必要な場合
- TransactionScope を使う場合など、Oracle.ManagedDataAccessDTC.dll が必要な時がある
- 無いと実行時に
FileNotFoundException
で死ぬ
- 無いと実行時に
- Oracle.ManagedDataAccess.dllと同様に、実行パスかGACに入ってればOK
- Microsoft Visual C++ 2010 SP1 再頒布可能パッケージ を必要とする点に注意 (SP1じゃなくても大丈夫だとは思うが…)
- これも同様に、インストールされていないと実行時に
FileNotFoundException
で死ぬ
- これも同様に、インストールされていないと実行時に
- Oracle.ManagedDataAccessDTC.dll も Microsoft Visual C++ 2010 SP1 再頒布可能パッケージ も32bit版と64bit版があるので、実行環境に合わせたものを使おう
[raw]
emctl stop dbconsole
emctl unsecure dbconsole
emctl start dbconsole
[/raw]
参考:Enterprise Managerコンポーネントの起動および停止
制限を解除すれば利用できるようになる。
[sql]
EXEC APEX_040100.APEX_SITE_ADMIN_PRIVS.UNRESTRICT_SCHEMA(p_schema => ‘SCOTT’);
COMMIT;
[/sql]
Download Oracle Application Express
Oracle Application Express 4.0 Install Guide インストールガイド
4.1.1を使う場合、翻訳バージョンのインストールの際
[sql]ALTER SESSION SET CURRENT_SCHEMA = APEX_040000;[/sql]
の部分は以下のようにする必要がある。
[sql]ALTER SESSION SET CURRENT_SCHEMA = APEX_040100;[sql]
バージョンに応じて適宜変更する必要があると考えられる。
Oracle JDBC Driver 10で確認。
必ず空文字””が返される。
「JDBC 開発者ガイドおよびリファレンス」に載ってるらしい。
- JDBC APIではPreparedStatementインタフェースを用いてパラメタライズドクエリを実行する
- OracleJDBCドライバではOraclePreparedStatementクラスを用いてパラメタライズドクエリを実行する
- OraclePreparedStatementのsetStringメソッドおよびsetCharメソッドは空白埋めを行わない
- OraclePreparedStatementのsetFixedCharメソッドは空白埋めを行う
- JDBCのPreparedStatementインタフェースにはsetCharおよびsetFixedCharメソッドは定義されていない
(これらはOracleのJDBC拡張機能を用いる事で実装できる)
要するに・・・
CHAR(5)型のCOL1列を持ったテーブルTABLE_Aに対して
[sql]SELECT * FROM TABLE_A WHERE COL1=?[/sql]
というSQLに比較文字列をバインドしてを発行する時、setString(1, "ABC")
とするとCOL1='ABC'
という比較がされ、確実に0件。
setString(1, "ABC ")
としなければならない。
OracleParameterdStatement.setFixedChar(int, String)
を使用することにより、空白埋め比較でバインドする事も出来るが、DBに依存したコードとなる。
ちなみにバインドをしないでリテラルで比較するとヒットする。
[sql]SELECT * FROM TABLE_A WHERE COL1=’ABC'[/sql]
これはOracleでは両辺にVARCHAR2型またはNVARCHAR2型が使用されている場合以外は、空白埋めで比較が行われるためである。
そもそも可変文字列の格納にCHAR型を使うのをやめればすむ話。。
参考:
- Oracle10gのJDBCは、DATE型項目の場合java.sql.Date型で返却するために時刻が欠落する。
- Oracle9.0.1より前のJDBCではjava.sql.Timestamp型で返却していたため時刻は欠落しない。
- Oracle11gもjava.sql.Timestamp型で返却する仕様をデフォルトとしているため時刻は欠落しない。
-
Oracle10gの場合、oracle.jdbc.V8Compatible=trueを指定することでjava.sql.Timestamp型で返却する動作となる。
参考:
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からの回答:
QUESTION
======
oracle.jdbc.V8Compatible=trueにすることで getObject()の戻り値の型がDate→Timestamp と変更される以外に動作が変わることがあるか。ANSWER
======
ございません。oracle.jdbc.V8Compatible=true に設定することによる動作の変更点はgetObject()の戻り値の型が Date→Timestamp と変更されるだけでございます。
DBへの型のマッピングは気をつけないとダメだよという話。
予備知識とか
- ANSI SQLのDATE型は日付のみ保持する。
- OracleのDATE型は日付だけでなく時刻まで保持する。(秒未満の精度とタイムゾーンは保持しない)
DATE型@Java
- java.sql.DateクラスはANSI準拠。日付までしか保持しない
- java.util.Dateクラスはミリ秒まで保持する。
- JDBCではjava.sql.DateクラスはDATE型(JDBC)にマッピングされる。
- JDBCではjava.util.DateクラスはDATE、TIME、TIMESTAMP型(JDBC)にマッピングされる。
問題例とか
- JavaでOracleに日付を登録する場合、やり方によっては時刻情報が落ちる。
- java.sql.Dateのコンストラクタはlong型なミリ秒を受け取れるが、残るのは日付のみ。
参考:
OracleSQLでは/**/の開始文字と終了文字は空白や改行でテキストから切り離す必要は無いが、SQL*Plusでは空けなければならない。
- スラッシュとアスタリスク(/*)を使用してコメントを開始します。コメントのテキストを続けます。このテキストは複数行にまたがってもかまいません。アスタリスクとスラッシュ(*/)を使用してコメントを終了します。開始文字と終了文字は、空白や改行によってテキストから切り離す必要はありません。
- –(ハイフン2個)を使用してコメントを開始します。コメントのテキストを続けます。このテキストは複数行にまたがることはできません。改行によってコメントを終了します。
SQLの入力に使用するツール製品には、追加の制限事項があるものもあります。たとえば、SQL*Plusを使用している場合、デフォルトでは複数行のコメント内に空白行を入れることはできません。詳細は、データベースのインタフェースとして使用するツール製品のドキュメントを参照してください。
SQLのコメント・デリミタ(/*…*/)は、スクリプト内の個別の行に入力するか、SQLコマンドと同じ行に入力するか、またはPL/SQLブロック内の行に入力します。
コメントの初めのスラッシュとアスタリスク(/*)の後に空白を入力する必要があります。
コメントは、次のように複数の行にわたっていてもかまいませんが、コメント内にコメントをネストさせることはできません。
to be run monthly. */
COLUMN LAST_NAME HEADING ‘LAST_NAME’;
COLUMN SALARY HEADING ‘MONTHLY SALARY’ FORMAT $99,999;
COLUMN COMMISSION_PCT HEADING ‘COMMISSION %’ FORMAT 90.90;
REMARK Includes only salesmen;
SELECT LAST_NAME, SALARY, COMMISSION_PCT
FROM EMP_DETAILS_VIEW
/* Include only salesmen.*/
WHERE JOB_ID=’SA_MAN’; [/sql]