TimesTenおよびTimesTen Cacheでは、CまたはC++プログラム用のOracle Call Interface (OCI)がサポートされます。
この章では、OCIに関する概要およびTimesTen固有の情報について説明し、特にTimesTenでのOCIの使用とOracle DatabaseでのOCIの使用の違いについて強調します。OCIの詳細は、Oracle Databaseライブラリの『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください。
第2章「ODBCでのTimesTenデータベースの使用」も参照してください。TimesTenの機能について興味深いと思われる情報が記載されています。
内容は次のとおりです。
OCIとは、データベースにアクセスしてSQL実行を制御するために使用可能な機能を備えたAPIのことです。OCIでは、CおよびC++プログラミング言語のデータ型、コール規則、構文およびセマンティックがサポートされています。すべてのCまたはC++プログラムと同様にOCIプログラムをコンパイルおよびリンクします。前処理またはプリコンパイルの手順はありません。
データベース・アクセスおよび検索機能のOCIライブラリは、実行時にアプリケーションにリンクできる動的なランタイム・ライブラリの形式になっています。OCIライブラリには、次の機能領域が含まれます。
SQLアクセス機能
データ型マッピングおよび操作機能
次に、OCIに用意されている、またはOCIでサポートされている多数の役立つ機能の一部を示します。
文のキャッシュ
動的SQL
トランザクション制御文、セッション制御文およびシステム制御文(DML文のような)を処理する機能
サーバー・メタデータのレイヤーを公開する記述機能
コミット・リクエストを文の実行と関連付けてラウンドトリップを減らす機能
ラウンドトリップを減らす透過的プリフェッチ・バッファを使用した問合せの最適化
OCIハンドルの相互排他ロックを不要にするスレッド・セーフティ
OCIの一般的な詳細は、Oracle Databaseドキュメント・セットに含まれている『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください。
この章では、TimesTenおよびTimesTen CacheでのOCIの使用に固有の情報を示します。サポートされている機能、TimesTen OCIの構文および使用方法は、Oracle Databaseと同じです。
この項の内容は次のとおりです。
TimesTen OCIサポートによって、既存の数多くのOCIアプリケーションをTimesTen直接接続またはクライアント/サーバー接続で実行できます。また、OCIをデータベース・インタフェースとして使用するPro*C/C++やODP.NETなどのその他の機能を使用することもできます。(OCI、Pro*C/C++およびODP.NETアプリケーションからPL/SQLをコールすることもできます。)図3-1に、TimesTenアーキテクチャにおけるOCIサポートの位置付けを示します。
TimesTenは、OCIクライアント・ライブラリとしてOracle Instant Clientを備えています。これは、『Oracle TimesTen In-Memory Databaseインストレーション・ガイド』
の環境変数に関する項で説明する、適切なttenvスクリプトを使用して構成します。
TimesTen 11gリリース2(11.2.2)OCIはOracle Databaseリリース11.2.0.2 OCIに基づいており、現在のOCI 8スタイルのAPIをサポートしています。たとえば、OCIStmtExecute()
関数はサポートされますが、これより古いoexec()
関数はサポートされません。Oracle Databaseドキュメントの『Oracle Call Interfaceプログラマーズ・ガイド』の廃止されたOCIルーチンに関する説明を参照してください。
この項では、グローバリゼーションのTimesTen OCIサポートについて説明します。
接続用のキャラクタ・セットを指定するには、OCIプログラムでNLS_LANG
環境変数を設定するか、またはOCIEnvNlsCreate()
をコールできます。NLS_LANG
またはOCIEnvNlsCreate()
によって上書きされない場合、sys.odbc.ini
またはユーザーodbc.ini
ファイルの設定がデフォルトで使用されます。キャラクタ・セットを明示的に設定することをお薦めします。通常、デフォルトはAMERICAN_AMERICA.US7ASCII
です。
TimesTen OCIでは言語またはロケール(地域)設定はサポートされていないため、前述のAMERICAN_AMERICA
などのNLS_LANG
の言語および地域コンポーネントは無視されます。ただし、言語およびロケールを指定しない場合にも、NLS_LANG
の設定時にキャラクタ・セットの前にピリオドを付ける必要があります。たとえば、AMERICAN_AMERICA
は無視されますが、次の設定はいずれも有効です。
NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
または
NLS_LANG=.WE8ISO8859P1
注意:
|
TimesTen OCIでは、他に、次のグローバリゼーション機能もサポートされます。これらの機能は、環境変数、TimesTenの一般接続属性またはTimesTen ODBC接続オプションとして設定できます。接続オプションの場合、ここでは名前の先頭に「TT_
」が追加されます。環境変数の設定は、対応する接続属性または接続オプションの設定よりも優先されます。接続オプションの設定は、対応する接続属性の設定よりも優先されます。
NLS_LENGTH_SEMANTICS
: デフォルトで、文字データ型CHAR
およびVARCHAR2
の長さは、文字数ではなくバイト数で指定します。シングルバイト文字エンコードの場合は、バイトでの指定は正しく機能します。マルチバイト文字エンコードの場合は、NLS_LENGTH_SEMANTICS
を使用して、かわりに文字長セマンティクスによってCHAR
列およびVARCHAR2
列を作成できます。サポートされている設定は、BYTE
(デフォルト)およびCHAR
です。(NCHAR
列およびNVARCHAR2
列は、常に文字ベースです。既存の列は影響を受けません。)
NLS_SORT
: 文字データのソートの種類を指定します。NLS_LANG
のデフォルト値よりも優先されます。有効な値は、BINARY
またはTimesTenでサポートされているすべての言語ソート名です。たとえば、ドイツ語の言語ソート順序を指定するには、NLS_SORT=German
と設定します。
NLS_NCHAR_CONV_EXCP
: NCHAR
またはNVARCHAR
データとCHAR
またはVARCHAR2
データの間の暗黙的または明示的なキャラクタ・タイプの変換中にデータが消失した場合に、エラーがレポートされるかどうかを指定します。有効な設定は、TRUE
およびFALSE
です。デフォルト値はFALSE
で、エラーはレポートされません。
これらの環境変数および関連機能の詳細は、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』のグローバリゼーションのサポートに関する説明および『Oracle Databaseグローバリゼーション・サポート・ガイド』のグローバリゼーション・サポート環境の設定に関する説明を参照してください。TimesTen接続オプションのサポートについては、「SQLSetConnectOptionおよびSQLGetConnectOptionのオプションのサポート」を参照してください。
この項では、Oracle DatabaseでのOCIとTimesTenでのOCIを比較した場合の制限事項および違いを、次の各項目について説明します。
TimesTenでは、TimesTenまたはTimesTen Cacheに存在しない機能に関連するOCIコールはサポートされていません。たとえば、TimesTenおよびTimesTen Cacheでは、次のOracle Database機能はサポートされていません。
アドバンスト・キューイング
ANYDATA
オブジェクトのサポート
コレクション
カートリッジ・サービス
ダイレクト・パス・ロード
日付/時間間隔
イテレータ
BFILE
暗号ツールキット
XML DBサポート
Spatialサービス
イベント処理
セッションの切替え
スクロール可能カーソル
TimesTen OCIには、次の制限があります。
TypeMode
データ・ストア属性は、Oracle Databaseの動作に対応する0に設定する必要があります。
DuplicateBindMode
一般接続属性は、Oracle Databaseの動作に対応する0に設定する必要があります。
DDLCommitBehavior
一般接続属性は、Oracle Databaseの動作に対応する0に設定する必要があります。
非同期コールはサポートされていません。
接続プーリングおよびセッション・プーリングはサポートされていません。
OCIDescribeAny()
でのオブジェクトの記述は、名前による記述のみがサポートされます。PL/SQLオブジェクトの記述はサポートされていません。(「サポートされているOCIコール」に記載されているこの関数のエントリも参照してください。)
TimesTenクライアント/サーバー自動クライアント・フェイルオーバーはサポートされていません。
TNSPING
ユーティリティでは、TimesTenへの接続は認識されていません。
INSERT
、UPDATE
およびDELETE
文からの暗黙的ROWID
値の取得はサポートされていません。(ただし、SELECT FOR UPDATE
文ではサポートされています。)
結果セットを返すTimesTen組込みプロシージャは、直接にはサポートされていません。ただし、この目的にPL/SQLを使用することはできます。「OCIでPL/SQLを使用してTimesTen組込みプロシージャをコール」を参照してください。
PL/SQLブロック、プロシージャ・コールまたは関数コールから単一のREF CURSORのみが返されます。
OCIBindArrayOfStruct()
およびOCIDefineArrayOfStruct()
による構造体のバインドおよび定義は、SQL文についてはサポートされていますが、PL/SQLについてはサポートされていません。(「サポートされているOCIコール」に記載されているこれらの関数のエントリも参照してください。)
SQL*PlusやSQL*LoaderなどのOracle Databaseユーティリティはサポートされていません。(TimesTenでは、SQL*PlusのかわりにttIsql
を、SQL*LoaderのかわりにttBulkCp
を使用できます。『Oracle TimesTen In-Memory Databaseリファレンス』のユーティリティに関する説明を参照してください。)
配列バインド(PL/SQL文に配列をバインドする機能)は、連想配列(索引付き表またはPL/SQL表)についてはサポートされていますが、VARRAY(変数サイズ配列)やネストされた表はサポートされていません。(「TimesTen OCIでの連想配列バインド」を参照してください。)
次の点に注意してください。
TimesTenとOracle DatabaseはどちらもXAをサポートしていますが、TimesTenではOCIを介したXAはサポートしていません。
OCIを使用すると、TimesTenでは、DML文に対する自動コミットが自動的に無効化されます。終了時に、トランザクションを明示的にコミットするか、ロールバックする必要があります。
TimesTenでは16進リテラルの使用方法に違いがあります。詳細は、『Oracle TimesTen In-Memory Database SQLリファレンス』の定数
でHexadecimalLiteralに関する説明を参照してください。
既存のOCIプログラムがあり、そのプログラムでTimesTenではサポートされていないOCI機能が使用されているかどうかを確認する場合は、ttSrcScan
コマンドライン・ユーティリティを使用すると、サポートされていない関数、型、型コード、属性、モードおよび定数に関してプログラムをスキャンできます。このユーティリティは、TimesTenまたはOracle Databaseがインストールされていない場合でも実行可能なスタンドアロン・ユーティリティであり、TimesTenでサポートされているどのプラットフォームでも動作します。入力としてソース・コード・ファイルを読み取り、出力としてHTMLおよびテキスト・ファイルを作成します。サポートされていない項目が検出されると、それらの項目はログに記録され、代替が示されます。ttSrcScan
実行可能ファイルは、TimesTenのインストール先のquickstart/sample_util
ディレクトリにあります。
入力ファイルまたはスキャン対象のプログラムのディレクトリ、およびttSrcScan
レポートの出力ディレクトリを指定します。その他のオプションも使用できます。詳細は、sample_util
ディレクトリにあるREADMEファイルを参照してください。
この項では、TimesTen OCIアプリケーションの開始に関する次の内容について説明します。
表3-1に、TimesTen OCIアプリケーションを実行するための環境変数を示します。設定は、特に記述のないかぎり、直接接続とクライアント/サーバー接続の両方に適用されます。
環境変数は、インストール後に必要に応じて、使用オペレーティング・システムに適用可能なTimesTenのinstall_dir
/bin/ttenv
スクリプトまたはquickstart/ttquickstartenv
スクリプトを使用して変更できます。ttenvの詳細は、『Oracle TimesTen In-Memory Databaseインストレーション・ガイド』の環境変数に関する説明
を参照してください。
クイック・スタート・デモに付属のTimesTen OCIファイルおよびPro*C/C++ Makeファイルを使用して、適切な環境設定を実行することもできます。これらのファイルは次の場所にあります。
quickstart/sample_code/oci/ quickstart/sample_code/proc/
注意: TimesTenで動作するOCIプログラムが適切に生成されるためには、OCIコンパイルにORACLE_HOME を設定しないでください(以前に設定されていた場合は設定解除してください)。 |
表3-1 TimesTen OCIの環境変数
変数 | 必須またはオプション | 設定 |
---|---|---|
|
必須 |
パス内で、TimesTen Instant ClientディレクトリがOracle Databaseライブラリより前になるように設定する必要があります。パスは、 bin/ttenv quickstart/ttquickstartenv ttenvの詳細は、『Oracle TimesTen In-Memory Databaseインストレーション・ガイド』の |
|
|
|
|
オプション |
OCIログオン・コールで 詳細は、「OCIからTimesTenデータベースへの接続」を参照してください。 |
|
オプション |
「キャラクタ・セット」を参照してください。キャラクタ・セット・コンポーネントのみが適用され、TimesTenでサポートされているキャラクタ・セットを示している必要があります。言語および地域の値は無視されます。 この環境変数は、TimesTenのデフォルトのキャラクタ・セットよりも優先されます。 |
|
オプション |
「その他のグローバリゼーション機能」を参照してください。ソート順序は、TimesTenでサポートされている値である必要があります。 この環境変数は、TimesTenの |
|
オプション |
「その他のグローバリゼーション機能」を参照してください。 この環境変数は、TimesTenの |
|
オプション |
「その他のグローバリゼーション機能」を参照してください。 この環境変数は、TimesTenの |
注意: 表に記載されているNLS接続属性の詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』のNLS一般接続属性に関する説明を参照してください。 |
OCIアプリケーションをコンパイルおよびリンクする手順について、Oracle DatabaseとTimesTenの間に変更は必要ありません。
Oracle Client 11.2.0.2ライブラリを使用するOCIプログラムは、TimesTenで実行するために再コンパイルまたは再リンクする必要はありません。
TimesTen OCIでは、Oracle Instant Clientを使用してTimesTenデータベースに接続します。Oracle Databaseに接続する場合と同様に、tnsnames
またはeasy connectのいずれかのネーミング・メソッドを使用してデータベースに接続できます。
この項の内容は次のとおりです。
tnsnames、簡易接続およびtnsnames.oraファイルの詳細は、『Oracle Database Net Services管理者ガイド』
のネーミング・メソッドの構成に関する項を参照してください。
注意:
|
TimesTenでは、tnsnames
構文がサポートされています。TimesTenのtnsnames.ora
エントリは、Oracle Databaseのtnsnames.ora
エントリを使用する場合と同じ方法で使用できます。
次に、tnsnames.ora
でのTimesTenエントリの構文を示します。
tns_entry = (DESCRIPTION = (CONNECT_DATA = (SERVICE_NAME = dsn) (SERVER = timesten_direct | timesten_client)))
ここで、tns_entry
は、エントリに割り当てる任意のTNS名です。これは、OCILogon()、OCILogon2()
およびOCIServerAttach()
コールでdbname
引数として使用できます。
ここで示されているように、DESCRIPTION
およびCONNECT_DATA
は必要です。
SERVICE_NAME
では、dsn
は、OCIアプリケーションを実行しているユーザーに見えるsys.odbc.ini
またはユーザーodbc.ini
ファイルで構成されているTimesTen DSNである必要があります。Windowsでは、DSNはODBC Data Source Administratorを使用して指定できます。『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』のTimesTenデータベースの管理に関する説明を参照してください。
SERVER
の場合は、timesten_direct
でTimesTenへの直接接続を指定するか、timesten_client
でクライアント/サーバー接続を指定します。timesten_client
を選択した場合、DSNをクライアント/サーバー・データベースとして構成する必要があります。
通常どおり、TimesTenサーバーのホストおよびポートは、sys.ttconnect.ini
ファイルのエントリからDSNに基づいて決定されます。『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』のTimesTen ClientおよびTimesTen Serverの使用に関する項を参照してください。
次に、直接接続のtnsnames.ora
エントリの例を示します。
my_tnsname = (DESCRIPTION = (CONNECT_DATA = (SERVICE_NAME = my_dsn) (SERVER = timesten_direct)))
TNS名my_tnsname
は、次のいずれかの方法で使用できます。
OCIログオン・コールでmy_tnsname
をdbname
引数に指定します。
dbname
に空の文字列を指定し、TWO_TASK
またはLOCAL
をmy_tnsname
に設定します。
次に例を示します。
OCILogon2(envhp, errhp, &svchp, (text *)"user1", (ub4)strlen("user1"), (text *)"pwd1", (ub4)strlen("pwd1"), (text *)"my_tnsname", (ub4)strlen((char*)"my_tnsname"), OCI_DEFAULT));
OCIログオンのコール・シーケンスの詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』の接続関数、認証関数および初期化関数に関する項を参照してください。
またはUNIXシステムでは、たとえば、my_tnsname
にTWO_TASK
を設定し、dbname
に空の文字列を指定してOCIログオン・コールを使用します。
OCILogon2(envhp, errhp, &svchp, (text *)"user1", (ub4)strlen("user1"), (text *)"pwd1", (ub4)strlen("pwd1"), (text *)"", (ub4)0, OCI_DEFAULT));
TimesTenでは簡易接続構文がサポートされており、tnsnames.ora
を構成しなくても接続できるため、Instant Clientパッケージがさらに便利になります。簡易接続文字列は、URLに似た次の形式の構文を使用します。
[//]host[:port]/service_name:server[/instance]
先頭のダブルスラッシュは任意です。ホスト名は、簡易接続構文を満たすように指定する必要があり、そうでない場合、TimesTenでは無視されます。慣例的に、名前localhost
がよく使用されます。ポートに指定した値も無視されます。クライアント/サーバー接続では、TimesTenサーバーのホストおよびポートは、TimesTen DSNに基づいてsys.ttconnect.ini
ファイルのエントリから決定されます。
service_name
にDSNを指定します。必要に応じて、server
に
timesten_clientまたはtimesten_direct
を指定します。
TimesTenでは、instance
フィールドは無視されます。指定する必要はありません。
たとえば、次の簡易接続文字列では、クライアント/サーバー・ライブラリを使用してTimesTenサーバーに接続します。sys.odbc.ini
ファイルのDSN ttclient
がクライアント/サーバー・データ・ソースとして解決され、sys.ttconnect.ini
ファイルで指定された対応するホストおよびポートに接続することを想定しています。
"localhost/ttclient:timesten_client"
次の簡易接続文字列は、TimesTenへの直接接続の場合のものです。DSN ttdirect
がsys.odbc.ini
で定義されることを想定しています。
"localhost/ttdirect:timesten_direct"
簡易接続文字列は次のいずれかの方法で使用できます。
OCIログオン・コールでdbname
引数に指定します。
dbname
に空の文字列を指定し、TWO_TASK
またはLOCAL
に簡易接続文字列を一重引用符で囲んで設定します。
次に例を示します。
OCILogon2(envhp, errhp, &svchp, (text *)"user1", (ub4)strlen("user1"), (text *)"pwd1", (ub4)strlen("pwd1"), (text *)"localhost/ttclient:timesten_client", (ub4)strlen((char*)"localhost/ttclient:timesten_client"), OCI_DEFAULT));
OCIログオンのコール・シーケンスの詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』の接続関数、認証関数および初期化関数に関する項を参照してください。
またはUNIXシステムでは、たとえば次のように、localhost/ttclient:timesten_client
にTWO_TASK
を設定し、dbname
に空の文字列を指定してOCIログオン・コールを使用します。
OCILogon2(envhp, errhp, &svchp, (text *)"user1", (ub4)strlen("user1"), (text *)"pwd1", (ub4)strlen("pwd1"), (text *)"", (ub4)0, OCI_DEFAULT));
sqlnet.ora
ファイルが存在する場合、このファイルは、試行するネーミング・メソッドおよびその試行順序を指定します。Instant Clientは、TNS_ADMIN
の場所でsqlnet.ora
ファイルを検索します(該当する場合)。TNS_ADMIN
ではなくORACLE_HOME
が設定されている場合(以前のInstant Clientをインストールしていた場合など)、デフォルトのsqlnet.ora
の場所は、Oracle Databaseのデフォルトの場所になります(Oracle Database Net Servicesリファレンスのsqlnet.oraファイルのパラメータに関する説明を参照)。
sqlnet.ora
が存在していても、特定のネーミング・メソッドを指定していない場合、そのメソッドは使用できません。sqlnet.ora
が存在しない場合は、いずれのメソッドも使用できます。
TimesTenでは、tnsnames.ora
およびsqlnet.ora
のサンプル・コピーはinstall_dir
/network/admin/samples
ディレクトリにあります。次に、TimesTenに用意されているsqlnet.ora
ファイルを示しますが、このファイルでは、tnsnames
と簡易接続(EZCONNECT
)の両方がサポートされます。
# To use ezconnect syntax or tnsnames, the following entries must be # included in the sqlnet.ora configuration. # NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)
TimesTenでは、このファイルによって、最初にOCIログオン・コール内のtnsnames
構文が検索されます。tnsnames
構文を検出できなかった場合、簡易接続構文が検索されます。
[myadmin]
のようにユーザー名を大カッコ内に指定し、パスワードを空の文字列("")として指定することで、OCIを介して外部で識別されたユーザー(外部ユーザー)として接続できます。
特に、TimesTenでは常に外部ユーザーであるインスタンス管理者として接続する場合に有効です。
外部で識別されたユーザーは、直接モードまたはローカル・ホスト上のデータベースへのクライアント/サーバー接続に使用できますが、リモート・ホスト上のデータベースへのクライアント/サーバー接続には使用できません。
前述の例を次のように変更します。
OCILogon2(envhp, errhp, &svchp, (text *)"[myadmin]", (ub4)strlen("[myadmin]"), (text *)"", (ub4)strlen(""), (text *)"my_tnsname", (ub4)strlen((char*)"my_tnsname"), OCI_DEFAULT));
この機能はOCIプロキシ構文を使用します。『Oracle Call Interfaceプログラマーズ・ガイド』のプロキシを介したクライアント・アクセスに関する説明を参照してください。
TimesTen OCIアプリケーションのエラーでは、Oracle Databaseのエラー・コードが返されます。TimesTenでは、同様の状況でOracleがレポートするOracle Databaseエラー・コードと同じエラー・コードをレポートしようとします。エラー・メッセージは、TimesTenカタログまたはOracle Databaseカタログのいずれかから取得されます。エラー・メッセージによっては、TimesTenエラー・コードを伴う場合もあります(該当する場合)。
致命的なエラーとは、エラー・リカバリが終わるまでデータベースにアクセスできなくなるエラーのことです。致命的なエラーが発生すると、メモリー不足状態を回避するために、すべてのデータベースの接続を切断する必要があります。それ以後の処理は完了されません。古いTimesTenインスタンスの共有メモリーは、エラー発生時にアクティブだったすべての接続が切断されるまで解放されません。
OCIでの致命的なエラーは、Oracle Databaseエラー・コードORA-03135
またはORA-00600
で示されます。これらのエラーの処理は、標準的なエラーの処理とは異なります。特に、アプリケーションのエラー処理コードにデータベースとの接続を切断するコードを含める必要があります。
OCIの診断フレームワークでは、アプリケーションで使用しているすべてのシグナル処理に影響する可能性のあるシグナル・ハンドラがインストールされます。OCIのシグナル処理は、sqlnet.ora
ファイルにDIAG_SIGHANDLER_ENABLED=FALSE
を設定することで無効化できます。詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』のOCIの障害診断に関する説明を参照してください。
この項では、TimesTen OCIを使用する開発者向けに次の内容について説明します。
OCIでは、準備コールはクライアントで実行される軽量処理であることが期待されています。TimesTenでこの期待との一貫性を実現し、クライアントとサーバー間の不要なラウンドトリップを回避するため、TimesTenクライアント・ライブラリに実装されたSQLPrepare
では、遅延準備と呼ばれる処理が実行されますが、この処理では、リクエストは要求されるまでサーバーに送信されません。詳細は、「TimesTenの遅延準備」を参照してください。
この項では、OCIアプリケーションからSQLまたはPL/SQLへのパラメータのバインドに関連する機能について説明します。
SQL文で重複したパラメータをバインドするための、2つのサポートされているモード(Oracleモードまたは従来のTimesTenモード)については、「SQL文での重複したパラメータのバインド」を参照してください。その項と同様に、次の問合せについて検討します。TimesTen OCIでは、Oracleモードのみがサポートされていることに注意してください。
SELECT * FROM employees WHERE employee_id < :a AND manager_id > :a AND salary < :b;
OCIでは、通常、Oracleモードの場合と同様に、パラメータaが2回出現すると別のパラメータとみなされます。ただし、OCIでは、
a
を両方ともOCIBindByPos()
への1つのコールとバインドすることができます。
OCIBindByPos(..., 1, ...); /* both occurrences of :a */ OCIBindByPos(..., 3, ...); /* occurrence of :b */
また、OCIでは2つのa
を別々にバインドすることもできます。
OCIBindByPos(..., 1, ...); /* first occurrence of :a */ OCIBindByPos(..., 2, ...); /* second occurrence of :a */ OCIBindByPos(..., 3, ...); /* occurrence of :b */
両方の場合で、パラメータb
は位置3に存在するとみなされていることに注意してください。
注意: また、OCIでは、OCIBindByName() を使用して位置ではなく、名前でバインドすることもできます。 |
連想配列(以前の索引付き表またはPL/SQL表)は、TimesTen PL/SQLでは、(たとえばOCIアプリケーションからの)IN
、OUT
またはIN OUT
バインド・パラメータとしてサポートされます。これにより、アプリケーションとデータベース間で効率的に配列データを渡すことができます。
連想配列は、キー/値のペアのセットです。TimesTenでは、連想配列バインド(PL/SQL内でのみの連想配列の使用を除く)、キーまたは索引は、整数(BINARY_INTEGER
またはPLS_INTEGER
)である必要があります。値は、同じデータ型を持つ単純なスカラー値である必要があります。たとえば、部門番号で索引付けされた部門マネージャの配列になります。索引は、作成された順序ではなく、ソートされた順序で格納されます。
次の例のように、PL/SQLから連想配列の型を宣言し、次に連想配列を宣言できます(INDEX BY
に注意)。
declare TYPE VARCHARARRTYP IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER; x VARCHARARRTYP; ...
Pro*C/C++の場合は、「TimesTen Pro*C/C++での連想配列バインド」を参照してください。
詳細は、Oracle TimesTen In-Memory Database PL/SQL開発者ガイドのアプリケーションからの連想配列の使用に関する説明を参照してください。
注意: 次のTimesTenでの制限事項に注意してください。
|
TimesTenでは、OCIBindByName()
およびOCIBindByPos()
関数のmaxarr_len
および*curelep
パラメータをサポートすることによって、OCIでの連想配列バインドがサポートされています。これらのパラメータは、バインドが連想配列であることを示すために使用されます。
これらの関数の完全なコール・シーケンスは次のとおりです。
sword OCIBindByName ( OCIStmt *stmtp, OCIBind **bindpp, OCIError *errhp, const OraText *placeholder, sb4 placeh_len, void *valuep, sb4 value_sz, ub2 dty, void *indp, ub2 *alenp, ub2 *rcodep, ub4 maxarr_len, ub4 *curelep, ub4 mode ); sword OCIBindByPos ( OCIStmt *stmtp, OCIBind **bindpp, OCIError *errhp, ub4 position, void *valuep, sb4 value_sz, ub2 dty, void *indp, ub2 *alenp, ub2 *rcodep, ub4 maxarr_len, ub4 *curelep, ub4 mode );
maxarr_len
および*curelep
パラメータで連想配列をバインドする場合、次のように使用されます。(連想配列をバインドしない場合は、0(ゼロ)に設定してください。)
maxarr_len
: これは、配列の最大長を示す入力パラメータです。これは、連想配列が対応できる要素の最大数です。
*curelep
: これは、現在の配列の長さを示す入力/出力パラメータです。文の実行前後の連想配列での実際の要素の数へのポインタです。
これらの関数の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』のOCIBindByName()およびOCIBindByPos()に関する説明を参照してください。
注意: TimesTenでは、OCIBindDynamic() 関数およびOCIBindByName() とOCIBindByPos() に対するOCI_DATA_AT_EXEC モード設定はサポートされていません。(Oracle Databaseでは、OCIBindDynamic() を使用して、データをat execモードで提供または受信し、実行時に追加のバインド属性を設定するためのユーザー定義のコールバック関数を登録できます。) |
例3-1では、OCIアプリケーションは、PL/SQLプロシージャで、整数配列および文字配列を対応するOUT
連想配列にバインドします。
例3-1 OCIからの連想配列へのバインド
次のSQL設定を前提とします。
DROP TABLE FOO; CREATE TABLE FOO (CNUM INTEGER, CVC2 VARCHAR2(20)); INSERT INTO FOO VALUES ( null, 'VARCHAR 1'); INSERT INTO FOO VALUES (-102, null); INSERT INTO FOO VALUES ( 103, 'VARCHAR 3'); INSERT INTO FOO VALUES (-104, 'VARCHAR 4'); INSERT INTO FOO VALUES ( 105, 'VARCHAR 5'); INSERT INTO FOO VALUES ( 106, 'VARCHAR 6'); INSERT INTO FOO VALUES ( 107, 'VARCHAR 7'); INSERT INTO FOO VALUES ( 108, 'VARCHAR 8'); COMMIT;
次のPL/SQLパッケージ定義を前提とします。これには、プロシージャP1
の定義内の出力連想配列c1
およびc2
のそれぞれに使用される、INTEGER
連想配列タイプNUMARRTYP
およびVARCHAR2
連想配列タイプVCHARRTYP
があります。
CREATE OR REPLACE PACKAGE PKG1 AS TYPE NUMARRTYP IS TABLE OF INTEGER INDEX BY BINARY_INTEGER; TYPE VCHARRTYP IS TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER; PROCEDURE P1(c1 OUT NUMARRTYP,c2 OUT VCHARRTYP); END PKG1; / CREATE OR REPLACE PACKAGE BODY PKG1 AS CURSOR CUR1 IS SELECT CNUM, CVC2 FROM FOO; PROCEDURE P1(c1 OUT NUMARRTYP,c2 OUT VCHARRTYP) IS BEGIN IF NOT CUR1%ISOPEN THEN OPEN CUR1; END IF; FOR i IN 1..8 LOOP FETCH CUR1 INTO c1(i), c2(i); IF CUR1%NOTFOUND THEN CLOSE CUR1; EXIT; END IF; END LOOP; END P1; END PKG1;
次のOCIプログラムは、PKG1.P1
をコールし、配列をP1
出力連想配列にバインドし、バインドした連想配列の内容を出力します。特にOCIBindByName()
関数は、バインドを行うためにコールすることに注意してください。
static OCIEnv *envhp; static OCIServer *srvhp; static OCISvcCtx *svchp; static OCIError *errhp; static OCISession *authp; static OCIStmt *stmthp; static OCIBind *bndhp[MAXCOLS]; static OCIBind *dfnhp[MAXCOLS]; STATICF VOID outbnd_1() { int i; int num[MAXROWS]; char* vch[MAXROWS][20]; unsigned int numcnt = 5; unsigned int vchcnt = 5; unsigned short alen_num[MAXROWS]; unsigned short alen_vch[MAXROWS]; unsigned short rc_num[MAXROWS]; unsigned short rc_vch[MAXROWS]; short indp_num[MAXROWS]; short indp_vch[MAXROWS]; /* Assume the process is connected and srvhp, svchp, errhp, authp, and stmthp are all allocated/initialized/etc. */ char *sqlstmt = (char *)"BEGIN PKG1.P1(:c1, :c2); END; "; for (i = 0; i < MAXROWS; i++) { alen_num[i] = 0; alen_vch[i] = 0; rc_num[i] = 0; rc_vch[i] = 0; indp_num[i] = 0; indp_vch[i] = 0; } DISCARD printf("Running outbnd_1.\n"); DISCARD printf("\n----> %s\n", sqlstmt); checkerr(errhp, OCIStmtPrepare(stmthp, errhp, sqlstmt, (unsigned int)strlen((char *)sqlstmt), (unsigned int) OCI_NTV_SYNTAX, (unsigned int) OCI_DEFAULT)); bndhp[0] = 0; bndhp[1] = 0; checkerr(errhp, OCIBindByName(stmthp, &bndhp[0], errhp, (char *) ":c1", (sb4) strlen((char *) ":c1"), (dvoid *) &num[0], (sb4) sizeof(num[0]), SQLT_INT, (dvoid *) &indp_num[0], (unsigned short *) &alen_num[0], (unsigned short *) &rc_num[0], (unsigned int) MAXROWS, (unsigned int *) &numcnt, (unsigned int) OCI_DEFAULT)); checkerr(errhp, OCIBindByName(stmthp, &bndhp[1], errhp, (char *) ":c2", (sb4) strlen((char *) ":c2"), (dvoid *) vch[0], (sb4) sizeof(vch[0]), SQLT_CHR, (dvoid *) &indp_vch[0], (unsigned short *) &alen_vch[0], (unsigned short *) &rc_vch[0], (unsigned int) MAXROWS, (unsigned int *) &vchcnt, (unsigned int) OCI_DEFAULT)); DISCARD printf("\nTo execute the PL/SQL statement.\n"); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (unsigned int) 1, (unsigned int) 0, (const OCISnapshot*) 0, (OCISnapshot*) 0, (unsigned int) OCI_DEFAULT)); DISCARD printf("\nHere are the results:\n\n"); DISCARD printf("Column 1, INTEGER: \n"); for (i = 0; i < numcnt; i++) { if (indp_num[i] == -1) DISCARD printf("-NULL- "); else DISCARD printf("%5d, ", num[i]); DISCARD printf("ind = %d, len = %d, rc = %d\n", indp_num[i], alen_num[i], rc_num[i]); } DISCARD printf("\nColumn 2, VARCHAR2(20): \n"); for (i = 0; i < vchcnt; i++) { if (indp_vch[i] == -1) DISCARD printf("-NULL- "); else DISCARD printf("%.*s, ", alen_vch[i], vch[i]); DISCARD printf("ind = %d, len = %d, rc = %d\n", indp_vch[i], alen_vch[i], rc_vch[i]); } DISCARD printf("\nDone\n"); return; }
注意: alen_* 配列は長さの配列、rc_* 配列はリターン・コードの配列、indp_* 配列はインジケータの配列です。 |
この項では、TimesTen Cacheの使用に関するTimesTen OCI機能について説明します。
TimesTen Cacheを使用するには、キャッシュされたOracle Database表からの選択およびその更新が可能なOracle Databaseユーザーと同じ名前を持つキャッシュ・ユーザーがTimesTenデータベースに存在している必要があります。たとえば、このOracle Databaseユーザーは、キャッシュ管理ユーザーまたはスキーマ・ユーザーになります。TimesTenキャッシュ・ユーザーのパスワードは、同じ名前を持つOracle Databaseユーザーと別のパスワードにすることができます。詳細は、『Oracle TimesTen Application-Tier Database Cacheユーザーズ・ガイド』のキャッシュ・インフラストラクチャの設定に関する説明を参照してください。
OCIをTimesTen Cacheで使用する場合、TimesTenでは、TimesTenへのログイン時にOCILogon()
またはOCILogon2()
コールのパスワード・フィールドにOracle Databaseユーザーのパスワードを追加することで、OCIを介してOracle Databaseユーザーのパスワードを渡すことができます。次の例のように、接続文字列で属性OraclePWD
を使用します。
text *cacheuser = (text *)"cacheuser1"; text *cachepwds = (text *)"ttpwd;OraclePWD=orclpwd"; text *ttdbname = (text *)"tt_tnsname"; .... OCILogon2(envhp, errhp, &svchp, (text *)cacheuser, (ub4)strlen(cacheuser), (text *)cachepwds, (ub4)strlen(cachepwds), (text *)ttdbname, (ub4)strlen(ttdbname), OCI_DEFAULT));
Oracle DatabaseユーザーのパスワードがTimesTenユーザーのパスワードと同じ場合でも、常にOraclePWD
を指定する必要があります。
この例での指定内容は次のとおりです。
TimesTenキャッシュ・ユーザーの名前(キャッシュされたOracle Database表にアクセスできるOracle Databaseユーザーの名前)は、cacheuser1
です。
TimesTenキャッシュ・ユーザーのパスワードはttpwd
です。
Oracle Databaseユーザーのパスワードは、orclpwd
です。
接続するTimesTenデータベースのTNS名は、tt_tnsname
です。
Oracle Databaseは、sys.odbc.ini
ファイルまたはユーザーodbc.ini
ファイルのTimesTen OracleNetServiceName
一般接続属性を使用して指定します。
あるいは、TNS名を使用するかわりに、簡易接続構文またはTWO_TASK
環境変数かLOCAL
環境変数を使用することもできます(前述の項を参照)。
TimesTen OCIでは、FLUSH CACHE GROUP
、LOAD CACHE GROUP
、REFRESH CACHE GROUP
またはUNLOAD CACHE GROUP
文の実行の後、OCI_ATTR_ROW_COUNT
引数を指定したOCI関数OCIAttrGet()
を使用すると、フラッシュ、ロード、リフレッシュまたはアンロードされたキャッシュ・インスタンスの数が返されます。
詳細は、『Oracle TimesTen Application-Tier Database Cacheユーザーズ・ガイド』の処理の影響を受けるキャッシュ・インスタンスの数の確認に関する説明を参照してください。
TimesTenではLOB(ラージ・オブジェクト)がサポートされています。これには、CLOB(Character LOB)、NCLOB(National Character LOB)およびBLOB(Binary LOB)が含まれます。
「LOBの使用」を参照してください。この項はODBC向けですが、LOBの概要、TimesTenとOracle Database LOBの違いおよびLOBのプログラミング・インタフェースについて説明しています。
この項では、LOBロケータ、一時LOBおよびOCI LOBのAPIおよび機能に重点を置いています。
TimesTenでのLOBの追加情報は、『Oracle TimesTen In-Memory Database SQLリファレンス』のLOBのデータ型に関する説明を参照してください。
TimesTenでは、BFILE、SecureFile、LOBに対する配列読取りおよび書込みまたはLOBのコールバック関数をサポートしていないことに注意し、LOBの詳細情報およびOCIでの使用方法は、『Oracle Call Interfaceプログラマーズ・ガイド』のLOBおよびBFILEの操作に関する説明を参照してください。
OCIに関して、次の内容について説明します。
注意: LOBのピース単位のデータ・インタフェースは、TimesTenでのOCIアプリケーションには適用されません。(ただし、LOBロケータ・インタフェースの機能を介して、LOBデータを分割して操作することはできます。) |
OCIでは、LOBロケータ・インタフェースが提供されており、インタフェースでは、LOBロケータとLOB値でLOBが構成されます。ロケータは値に対するハンドルとして機能します。アプリケーションがデータベースからLOBを選択すると、ロケータを受信ます。LOBの更新はロケータを介して行われます。LOBをパラメータとして渡す場合、実際の値ではなくロケータが渡されます。「OCIでのLOBロケータ・インタフェースの使用」を参照してください。(OCIでは、ロケータが関与しない簡易データ・インタフェースも使用できます。「OCIでのLOBの簡易データ・インタフェースの使用」を参照してください。)
LOBを更新するには、トランザクションでLOBが含まれる行に対する排他ロックが必要です。この操作を行うには、SELECT ... FOR UPDATE
文でLOBを選択します。これを行うと、ロケータが書込み可能になります。単純なSELECT
文では、ロケータは読取り専用です。読取り専用ロケータおよび書込み可能なロケータの動作は、次のとおりです。
読取り専用ロケータは読取り一貫性で、これは、有効期間を通して選択された時点のLOBの内容のみが確認されるという意味です。これには、LOBが選択されるより前の同じトランザクション内でLOBに対して行われた、コミットされていない更新も含まれることに注意してください。
書込み可能なロケータは、ロケータを介して書込みが行われるたびに、データベースからの最新データで更新されます。そのため、各書込みは最新のLOBのデータに対して行われ、他のロケータに対して行われた更新も含まれます。
次の例は、同じLOBに対する2つの書込み可能なロケータの動作を示します。
LOB列に「XY」が含まれています。
ロケータL1
を選択して更新します。
ロケータL2
を選択して更新します。
L1
を介してオフセット1に「Z」を書き込みます。
ロケータL1
を介して読み取ります。「ZY」が戻されます。
ロケータL2
を介して読み取ります。L2
は書込みに使用されるまで読取り一貫性を維持するため、「XY」が戻されます。
L2
を介してオフセット2に「W」を書き込みます。
ロケータL2
を介して読み取ります。「ZW」が戻されます。前述の手順の書込みの前に、ロケータが最新データ(「ZY」)で更新されました。
一時LOBはアプリケーション内にのみ存在し、TimesTen OCIでは、存続期間は作成されたトランザクションを超えません(TimesTenでのすべてのLOBロケータの存続期間と同様)。一時LOBをLOBデータのスクラッチ領域と考えることができます。
OCIアプリケーションは、アプリケーション内で使用するために、適切なAPIを介して、一時LOBをインスタンス化できます。(「OCIでのLOBロケータ・インタフェースの使用」を参照してください。)一時LOBは、TimesTenによって暗黙的に作成されることもあります。たとえば、SELECT
文で追加の文字列が連結されたLOBを選択した場合に、連結されたデータを含むためにTimesTenによって一時LOBが作成され、OCIアプリケーションは、その一時LOBのロケータを受信します。
一時LOBは、TimesTenの一時データ領域に格納されます。
TimesTen LOB実装とOracle Database実装の主な違いは、TimesTenでは、LOBロケータはトランザクションの終了後は有効ではないことです。すべてのLOBロケータは、(明示的、暗黙的のどちらの場合も)コミットまたはロールバックの後は無効化されます。これには、TimesTen DDLCommitBehavior
が0(ゼロ)(デフォルト)に設定されている場合(Oracle Databaseの動作に対応)、すべてのDDL文の実行後が含まれます。
「TimesTen LOBとOracle Database LOBの相違点」も参照してください。
簡易データ・インタフェースでは、その他のスカラー・データ型と同様に、バインドおよび定義することによって、アプリケーションによるLOBデータへのアクセスが可能です。アプリケーションでは、対応する変数タイプと互換性のあるLOB型を使用できます。OCIStmtPrepare()
を使用して、文を準備します。パラメータのバインドには、OCIBindByName()
またはOCIBindByPos()
を使用します。結果列の定義には、OCIDefineByPos()
を使用します。
たとえば、OCIアプリケーションは、データ型がSQLT_CHR
のOCIBindByName()
をコールすることによって、CLOBパラメータをバインドできます。OCIStmtExecute()
を使用して文を実行します。NCLOBパラメータの場合は、データ型SQLT_CHR
を使用し、OCIのcsform
属性(OCI_ATTR_CHARSET_FORM
)をSQLCS_NCHAR
に設定します。BLOBパラメータの場合は、データ型SQLT_BIN
を使用できます。
OCIを介した簡易データ・インタフェースの使用例を次に示します。
注意: 簡易データ・インタフェース(OCIBindByName() 、OCIBindByPos() またはOCIDefineByPos() )のバインドのサイズは64KBに制限されます。 |
例3-2 表および変数の例
以降の例では、ここに表示されている表および変数を前提にします。
person(ssn number, resume clob) OCIEnv *envhp; OCIServer *srvhp; OCISvcCtx *svchp; OCIError *errhp; OCISession *authp; OCIStmt *stmthp; /* Bind Handles */ OCIBind *bndp1 = (OCIBind *) NULL; OCIBind *bndp2 = (OCIBind *) NULL; /* Define Handles */ OCIDefine *defnp1 = (OCIDefine *) NULL; OCIDefine *defnp2 = (OCIDefine *) NULL; #define DATA_SIZE 50 #define PIECE_SIZE 10 #define NPIECE (DATA_SIZE/PIECE_SIZE) char col2[DATA_SIZE]; char col2Res[DATA_SIZE]; ub2 col2len = DATA_SIZE; sb4 ssn = 123456; ... text *ins_stmt = (text *)"INSERT INTO PERSON VALUES (:1, :2)"; text *sel_stmt = (text *)"SELECT * FROM PERSON_1 ORDER BY SSN"; ...
表3-3 簡易データ・インタフェースを使用したLOBデータの挿入
この例では、OCIでの簡易データ・インタフェースを使用してINSERT
文を実行します。この例では、変数ins_stmtで定義したINSERT
文を含む、前述の例3-2
の表および変数を使用します。
for (i=0;i<DATA_SIZE;i++) col2[i] = 'A'; /* prepare SQL insert statement */ OCIStmtPrepare (stmthp, errhp, ins_stmt, strlen(ins_stmt), OCI_NTV_SYNTAX, OCI_DEFAULT); /* bind parameters 1 and 2 using OCI_DEFAULT (not data-at-exec) */ OCIBindByPos (stmthp, &bndp1, errhp, 1, (dvoid *) &ssn, sizeof(ssn), SQLT_INT, 0, 0, 0, 0, 0, OCI_DEFAULT); OCIBindByPos (stmthp, &bndp2, errhp, 2, (dvoid *) col2, col2len, SQLT_CHR, 0, 0, 0, 0, 0, OCI_DEFAULT); /* execute insert statement */ OCIStmtExecute (svchp, stmthp, errhp, 1, 0, 0, 0, OCI_DEFAULT);
表3-4 簡易データ・インタフェースを使用したLOBデータの選択
この例では、OCIでの簡易データ・インタフェースを使用してSELECT
文を実行します。この例では、変数sel_stmtで定義したSELECT
文を含む、前述の例3-2
の表および変数を使用します。
/* prepare select statement */ OCIStmtPrepare (stmthp, errhp, sel_stmt, strlen(sel_stmt), OCI_NTV_SYNTAX, OCI_DEFAULT); /* define result columns 1 and 2 using OCI_DEFAULT (not data-at-exec) */ OCIDefineByPos (stmthp, &defnp1, errhp, 1, (dvoid*) &ssn, sizeof(ssn), SQLT_INT, 0, 0, 0, OCI_DEFAULT); OCIDefineByPos (stmthp, &defnp2, errhp, 2, (dvoid *) col2Res, sizeof(col2), SQLT_CHR, 0, &col2len, 0, OCI_DEFAULT); /* execute select statement */ OCIStmtExecute (svchp, stmthp, errhp, (ub4)1, (ub4)0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT)); /* col2Res should now have a DATA_SIZE sized string of 'A's. */
OCI LOBロケータ・インタフェースは、データベースまたは一時LOB(ピース単位またはチャンク全体)のどちらとも使用できます。
LOBロケータ・インタフェースを使用するには、アプリケーションに有効なLOBロケータが必要です。一時LOBの場合、これは、OCILobCreateTemporary()
コールにより明示的に、または一時LOBを作成するSQL文(たとえば、SELECT c1 || c2 FROM myclob
)により暗黙的に取得できます。永続LOBの場合は、SQL文を使用してデータベースからLOBロケータを取得します。(例はこの項で後述します。)
バインド・タイプは、CLOBではSQLT_CLOB
、BLOBではSQLT_BLOB
です。NCLOBの場合は、SQLT_CLOB
を使用し、OCIのcsform
属性(OCI_ATTR_CHARSET_FORM
)をSQLCS_NCHAR
に設定します。
TimesTenでは、特にBFILE、SecureFile、LOBに対する配列の読取りおよび書込みまたはLOBのコールバック関数を対象とした機能がサポートされていないことに注意し、詳細情報とOCI LOB関数のその他の例は、『Oracle Call Interfaceプログラマーズ・ガイド』のLOBの関数に関する説明を参照してください。
重要: LOBロケータを使用してAPIを介してLOBを操作すると、TimesTenの一時領域を使用することになります。このような操作を多数行うことで、TimesTenの一時データ領域のサイズ増加が必要となる場合があります。『Oracle TimesTen In-Memory Databaseリファレンス』のTempSizeに関する説明を参照してください。 |
注意:
|
OCIアプリケーションは、ロケータを割り当てるためのOCIDescriptorAlloc()
の最初のコール後に、LOBロケータの入力/出力パラメータを含むOCILobCreateTemporary()
関数を使用して一時LOBを作成できます。終了後に、OCIDescriptorFree()
を使用してロケータの割当てを解放し、OCILobFreeTemporary()
を使用して一時LOB自身を解放します。
重要: TimesTenでは、一時LOBを作成すると、データベース・トランザクションがまだ進行していない場合は、データベース・トランザクションが作成されます。エラーとなる状況を回避するには、コミットまたはロールバックを実行してトランザクションをクローズする必要があります。 |
TimesTenでは、Oracle Databaseによってサポートされるすべての期間(OCI_DURATION_SESSION
、 OCI_DURATION_TRANSACTION
またはOCI_DURATION_CALL
)は、OCILobCreateTemporary()
で許容されますが、TimesTenでは、一時LOBの存続期間はトランザクション存続期間を超えることはありません。
次のシナリオでは、一時LOBの存続期間はトランザクション存続期間より短くなることに注意してください。
OCI_DURATION_CALL
が指定されている場合
トランザクションの終了前に、アプリケーションが、ロケータでOCILobFreeTemporary()
をコールした場合
アプリケーションで、一時LOBのユーザーが指定した期間を開始するためにOCIDurationBegin()
をコールし、トランザクションの終了前にOCIDurationEnd()
をコールした場合
前述したOCI LOB関数の一部の例を次に示します。一時LOBの使用の詳細と完全な例は、『Oracle Call Interfaceプログラマーズ・ガイド』の一時LOBのサポートに関する説明を参照してください。
if (OCIDescriptorAlloc((void*)envhp, (void **)&tblob,(ub4)OCI_DTYPE_LOB, (size_t)0, (void**)0)) { printf("failed in OCIDescriptor Alloc in select_and_createtemp \n"); return OCI_ERROR; } ... if (OCILobCreateTemporary(svchp, errhp, tblob, (ub2)0, SQLCS_IMPLICIT, OCI_TEMP_BLOB, OCI_ATTR_NOCACHE, OCI_DURATION_TRANSACTION)) { (void) printf("FAILED: OCILobCreateTemporary() \n"); return OCI_ERROR; } ... if(OCILobFreeTemporary(svchp,errhp,tblob)) { printf ("FAILED: OCILobFreeTemporary() call \n"); return OCI_ERROR; }
アプリケーションでは通常、SQL文を使用してLOBロケータを取得またはロケータにアクセスし、次に、適切なAPI関数をロケータに渡すことによって、データベースからLOBにアクセスします。
EMPTY_CLOB()
またはEMPTY_BLOB()
SQL関数を使用して作成されたLOBには、有効なロケータがあり、アプリケーションはこのロケータを使用し、選択することでLOBにデータを挿入します。
次の表定義を想定します。
CREATE TABLE clobtable (x NUMBER, y DATE, z VARCHAR2(30), lobcol CLOB);
INSERT
文を準備します。次に例を示します。
INSERT INTO clobtable ( x, y, z, lobcol ) VALUES ( 81, sysdate, 'giants', EMPTY_CLOB() ) RETURNING lobcol INTO :a;
または、データを使用してLOBを初期化します。
INSERT INTO clobtable ( x, y, z, lobcol ) VALUES ( 81, sysdate, 'giants', 'The Giants finally won a World Series' ) RETURNING lobcol INTO :a;
記載されているとおり、LOBロケータを:a
にバインドします。
文を実行します。実行後、ロケータは新しく作成されたLOBを参照します。
アプリケーションは、LOBロケータ・インタフェースを使用して、ロケータを介してLOBデータの読取りまたは書込みが可能です。
または、アプリケーションはSELECT
文を使用して、既存LOBのロケータにアクセスできます。
例3-5 LOBロケータ・インタフェースを使用したLOBロケータの選択
この例では、次の表を使用します。
person(ssn number, resume clob)
PERSON
表のLOB列用のロケータを選択します。
text *ins_stmt = (text *)"INSERT INTO PERSON VALUES (:1, :2)"; text *sel_stmt = (text *)"SELECT * FROM PERSON WHERE SSN = 123456"; text *ins_empty = (text *)"INSERT INTO PERSON VALUES ( 1, EMPTY_CLOB())"; OCILobLocator *lobp; ub4 amtp = DATA_SIZE; ub4 remainder = DATA_SIZE; ub4 nbytes = PIECE_SIZE; /* Allocate lob locator */ OCIDescriptorAlloc (envhp, &lobp, OCI_DTYPE_LOB, 0, 0); /* Insert an empty locator */ OCIStmtPrepare (stmhp, errhp, ins_empty, strlen(ins_empty), OCI_NTV_SYNTAX, OCI_DEFAULT); OCIStmtExecute (svchp, stmhp, errhp, 1, 0, 0, 0, OCI_DEFAULT); /* Now select the locator */ OCIStmtPrepare (stmhp, errhp, sel_stmt, strlen(sel_stmt), OCI_NTV_SYNTAX, OCI_DEFAULT); /* Call define for the lob column */ OCIDefineByPos (stmthp, &defnp2, errhp, 1, &lobp, 0 , SQLT_CLOB, 0, 0, 0, OCI_DEFAULT); OCIStmtExecute (svchp, stmhp, errhp, 1, 0, 0, 0, OCI_DEFAULT);
OCIアプリケーションはOCILobOpen()
およびOCILobClose()
を使用して、LOBをオープンおよびクローズできます。LOBを明示的にオープンまたはクローズしない場合は、読取りまたは書込みの前に暗黙的にオープンされ、トランザクションの終了時に暗黙的にクローズされます。
アプリケーションでは、OCILobRead()
またはOCILobRead2()
を使用してLOBデータを読み取り、OCILobWrite()
またはOCILobWrite2()
を使用してLOBデータを書き込み、OCILobWriteAppend()
またはOCILobWriteAppend2()
を使用してLOBデータに追加し、OCILobErase()
またはOCILobErase2()
を使用してLOBデータを消去し、その他の様々なOCI関数を使用してその他の様々なアクションを実行します。
たとえば、「Hello World!」という内容のCLOBについて考えてみます。OCILobWrite()
をコールして、オフセット7に「I am a new string」と書き込むようにデータを上書きおよび追加できます。この結果、CLOBの内容が「Hello I am a new string」に更新されます。または、元の「Hello World!」からデータを消去する場合、オフセット7、量(文字数)5などを指定してOCILobErase()
をコールすると、CLOBを「Hello !」(空白が6つ)に更新できます。
OCI LOBロケータ・インタフェースのすべての関数については、『Oracle Call Interfaceプログラマーズ・ガイド』のLOB関数に関する説明を参照してください。
注意:
|
例3-6 LOBロケータ・インタフェースを使用したLOBデータの読取りおよび書込み
この例では、OCI LOB関数OCILobWrite()
を使用したLOBデータの書込み方法およびOCILobRead()
を使用したデータの読取り方法を示します。前述の例3-5の表および変数を使用します。
for (i=0;i<DATA_SIZE;i++) col2[i] = 'A'; /*************** Writing to the LOB *****************/ amt = DATA_SIZE; offset = 1; /* Write contents of col2 buffer into the LOB in a single chunk via locator lobp */ OCILobWrite (svchp, errhp, lobp, &amt, offset, col2, DATA_SIZE, OCI_ONE_PIECE, 0, 0, 0, SQLCS_IMPLICIT); /*************** Reading from the LOB *****************/ /* Get the length of the LOB */ OCILobGetLength (svchp, errhp, lobp, &len); amt = len; /* Read the LOB data in col2Res in a single chunk */ OCILobRead (svchp, errhp, lobp, &amt, offset, col2Res, DATA_SIZE, 0, 0, 0, SQLCS_IMPLICIT);
OCIでは、LOBごとにクライアント側のバッファリング用の機能が提供されています。この機能は、LOBでOCILobEnableBuffering()
をコールすることで有効化され、OCILobDisableBuffering()
をコールすること無効化されます。
LOBロケータに対するバッファリングを有効化することで、512KBの書込みバッファが作成されます。このサイズは設定できません。アプリケーションによってLOBロケータを介して書き込まれたデータはバッファされます。可能な場合、クライアント・ライブラリは、LOBの読取りリクエストにバッファからも対応します。アプリケーションは、OCILobFlushBuffer()
をコールすることによってバッファをフラッシュできます。バッファが一杯になっても自動的にはフラッシュされないため、バッファが一杯のときにロケータを介してLOBに書込みを試みると、エラーが発生することに注意してください。
次の制限事項は、クライアント側のバッファリングを使用している場合に適用されます。
バッファリングは、OCILobAppend()
、OCILobCopy()
、OCILobCopy2()
、OCILobErase()
、OCILobGetLength()
、OCILobTrim()
、OCILobWriteAppend()
およびOCILobWriteAppend2()
の各関数とは互換性がありません。
アプリケーションでは、LOBの最後に追加する場合にのみOCILobWrite()
またはOCILobWrite2()
を使用できます。
LOBデータは、アプリケーションがバッファをフラッシュした後にのみ、SQLおよびPL/SQL(サーバー側)操作に表示されます。
フラッシュされていないクライアント側の書込みがバッファにあるときにLOBが選択されると、そのフラッシュされていないデータは選択に含まれません。
クライアント/サーバー接続でサーバーへのラウンドトリップを減らすには、データベースからLOBデータをプリフェッチし、フェッチ操作中にクライアント側にキャッシュできます。OCIでのLOBのプリフェッチには、Oracle Databaseと同じ機能がTimesTenにあります。
次のOCI属性を使用してLOBのプリフェッチを構成します。サイズは、BLOBの場合はバイトで、CLOBまたはNCLOBの場合は文字数で表すことに注意してください。
OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE
: これを使用してプリフェッチを有効化し、デフォルトのプリフェッチ・サイズを指定します。値0(ゼロ)(デフォルト)はプリフェッチを無効化します。
OCI_ATTR_LOBPREFETCH_SIZE
: この属性を列定義ハンドルに設定し、特定のLOB列に対するプリフェッチ・サイズを指定します。
OCI_ATTR_LOBPREFETCH_LENGTH
: この属性はTRUE
またはFALSE
(デフォルト)に設定でき、LOBの長さやチャンクのサイズなどのLOBのメタデータをプリフェッチします。
OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE
とOCI_ATTR_LOBPREFETCH_LENGTH
の設定は互いに独立しています。LOBデータのプリフェッチは、LOBメタデータのプリフェッチから切り離して使用できます。
詳細および例は、『Oracle Call Interfaceプログラマーズ・ガイド』のLOBデータのプリフェッチ、長さおよびチャンクのサイズに関する説明を参照してください。
注意: 前述の属性設定は、TimesTenの直接接続では無視されます。 |
パススルーLOB(TimesTenを介してアクセスされるOracle DatabaseのLOB)は、TimesTen LOBとして公開され、TimesTenによってTimesTen LOBとほぼ同じようにサポートされますが、次の点に注意してください。
パススルーLOBの作成に、OCILobCreateTemporary()
は使用できません。
1つのTimesTen LOBを別のTimesTen LOBにコピーすること(OCILobCopy()
、OCILobCopy2()
、OCILobAppend()
などを使用して)に加えて、TimesTen LOBをパススルーLOBに、パススルーLOBからTimesTen LOBに、1つのパススルーLOBから別のパススルーLOBにコピーできます。これらのコピーでは、LOBの値をターゲットの宛先にコピーします。たとえば、パススルーLOBのTimesTen LOBへのコピーでは、LOBの値がTimesTenデータベースにコピーされます。
パススルーLOBのサイズがTimesTen LOBのサイズ制限より大きい場合、パススルーLOBをTimesTen LOBにコピーしようとするとエラーが発生します。
TimesTen LOBのサイズ制限は、パススルーによるOracle DatabaseのLOBの格納には適用されません。パススルーLOBがTimesTen LOBにコピーされた場合、サイズ制限はコピーにも適用されます。
TimesTenのローカルLOBと同様に、パススルーLOBのロケータは、トランザクションの終了後は有効ではありません。
例3-7 TimesTen LOBとパススルーLOB間のコピー
この例では、TimesTen LOBとOracle Database上のパススルーLOB間のコピーでの重要な機能を強調しています。表およびデータの設定後に、最初の例では、OCILobAppend()
を使用してLOBデータをOracle DatabaseからTimesTenにコピーし、2番目目の例では、OCILobCopy()
を使用してLOBデータをTimesTenからOracle Databaseにコピーしています。(どちらのコールも、どちらの場合にも使用できます。)次に、対比のために、3番目の例では、UPDATE
文を使用してLOBデータをOracle DatabaseからTimesTenにコピーし、4番目の例では、INSERT
文を使用してLOBデータをTimesTenからOracle Databaseにコピーしています。
/* Table and data setup */ call ttoptsetflag(''passthrough'', 3)'; DROP TABLE oratab'; CREATE TABLE oratab (i INT, c CLOB)'; INSERT INTO oratab VALUES (1, ''Copy from Oracle to TimesTen'')'; INSERT INTO oratab VALUES (2, EMPTY_CLOB())'; COMMIT; call ttoptsetflag(''passthrough'', 0)'; DROP TABLE tttab'; CREATE TABLE tttab (i INT, c CLOB)'; INSERT INTO tttab VALUES (1, ''Copy from TimesTen to Oracle'')'; INSERT INTO tttab VALUES (2, EMPTY_CLOB())'; INSERT INTO tttab VALUES (3, NULL)'; COMMIT; /* Table and data setup end */ /* * Below are four OCI pseudocode examples, for copying LOBs between * TimesTen and Oracle using OCI API and INSERT/UPDATE statements. */ /* Init OCI Env */ /* Set the passthrough level to 1 */ OCIStmtPrepare (..., "call ttoptsetflag(''passthrough'', 1)'", ...); OCIStmtExecute (...); /* * 1. Copy a passthrough LOB on Oracle to a TimesTen LOB */ /* Select a passthrough locator on Oracle */ OCIStmtPrepare (..., "SELECT c FROM oratab WHERE i = 1", ...); OCIDefineByPos (..., (dvoid *)&ora_loc_1, 0 , SQLT_CLOB, ...); OCIStmtExecute (...); /* Select a locator on TimesTen for update */ OCIStmtPrepare (..., "SELECT c FROM tttab WHERE i = 2 FOR UPDATE", ...); OCIDefineByPos (..., (dvoid *)&tt_loc_2, 0 , SQLT_CLOB, ...); OCIStmtExecute (...); /* Copy a passthrough LOB on Oracle to a TimesTen LOB */ OCILobAppend(..., tt_loc_2, ora_loc_1); /* * 2. Copy a TimesTen LOB to a passthrough LOB on Oracle */ /* Select a passthrough locator on Oracle for update */ OCIStmtPrepare (..., "SELECT c FROM oratab WHERE i = 2 FOR UPDATE", ...); OCIDefineByPos (..., (dvoid *)&ora_loc_2, 0 , SQLT_CLOB, ...); OCIStmtExecute (...); /* Select a locator on TimesTen */ OCIStmtPrepare (..., "SELECT c FROM tttab WHERE i = 1", ...); OCIDefineByPos (..., (dvoid *)&tt_loc_1, 0 , SQLT_CLOB, ...); OCIStmtExecute (...); /* Copy a passthrough LOB on Oracle to a TimesTen LOB */ OCILobCopy(..., ora_loc_2, tt_loc_1, 28, 1, 1); /* * 3. UPDATE a TimesTen LOB with a passthrough LOB on Oracle */ /* A passthrough LOB, (selected above in case 1) is bound to an UPDATE statement * on TimesTen table */ OCIStmtPrepare (..., "UPDATE tttab SET c = :1 WHERE i = 3", ...); OCIBindByPos (..., (dvoid *)&ora_loc_1, 0 , SQLT_CLOB, ...); OCIStmtExecute (...); /* * 4. INSERT a passthrough table on Oracle with a TimesTen LOB */ /* A TimesTen LOB, (selected above in case 2) is bound to an INSERT statement * on a passthough table on Oracle */ OCIStmtPrepare (..., "INSERT INTO oratab VALUES (3, :1)", ...); OCIBindByPos (..., (dvoid *)&tt_loc_1, 0 , SQLT_CLOB, ...); OCIStmtExecute (...); OCITransCommit (...); /* Cleanup OCI Env */
この章で前述したように、結果セットを返すTimesTen組込みプロシージャは、OCIを通じて直接にはサポートされていません。ただし、例3-8のように、この目的にPL/SQLを使用することはできます。
例3-8 OCIでPL/SQLを使用してTimesTen組込みプロシージャをコール
plsql_resultset_example(OCIEnv *envhp, OCIError *errhp, OCISvcCtx *svchp) { OCIStmt *stmhp; OCIBind *bindp; sb4 passThruValue = -1; char v_name[255]; text *stmt_text; /* prepare the plsql statement */ stmt_text = (text *) "declare v_name varchar2(255); " "begin execute immediate " "'call ttOptGetFlag(''passthrough'')' into v_name, :rc1; " "end;"; OCIStmtPrepare2(svchp, &stmhp, errhp, (text *)stmt_text, (ub4)strlen((char *)stmt_text), (text *)0, (ub4)0, (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT); /* bind parameter 1 (:v_name) to varchar2 out-parameter */ OCIBindByPos(stmhp, &bindp, errhp, 1, (dvoid*)&v_name, sizeof(v_name), SQLT_CHR, (dvoid*)0, (ub2*)0, (ub2*)0, (ub4)0, (ub4*)0, OCI_DEFAULT); /* execute the plsql statement */ OCIStmtExecute(svchp, stmhp, errhp, (ub4)1, (ub4)0, (OCISnapshot *)0, (OCISnapshot *)0, (ub4)OCI_DEFAULT); /* convert the passthrough string value to an integer */ passThruValue = (sb4)atoi((const char *)v_name); printf("Value of the passthrough flag is %d\n", passThruValue); /* drop the statement handle */ OCIStmtRelease(stmhp, errhp, (text *)0, (ub4)0, (ub4)OCI_DEFAULT); }
この項では、OCI機能のTimesTenによるサポートのリファレンスに関して、次の項目について説明します。
表3-2に、Oracle Databaseリリース11.2.0.2に関して記述されている、OCIコールに対するTimesTenサポートを示します。
一部のコールのグループは、名前にアスタリスクを付けて示しています。たとえば、TimesTenでサポートされていないアドバンスト・キューイングに関連するコールは、OCIAQ
で始まる名前を持ち、表ではOCIAQ*()
と示されています。TimesTenでサポートされているOCI日付関数は、OCIDate*()
と示されています。
表3-2 TimesTen OCIでサポートされているコール
OCIコール | サポート | 注意 |
---|---|---|
|
なし |
TimesTenでは、アドバンスト・キューイングはサポートされていません。 |
|
なし |
TimesTenではANYDATAはサポートされていません。 |
|
あり |
|
|
あり |
|
|
あり |
|
|
あり |
|
|
あり |
TimesTenサポートには、キャッシュ・グループでの特別な使用方法が含まれています。「TimesTen OCIでのTimesTen Cache」を参照してください。 |
|
あり |
|
|
なし |
TimesTenでは、XML DBはサポートされていません。 |
|
あり |
SQL文ではサポートされていますが、PL/SQLではサポートされていません。 |
|
あり |
次の値は
|
|
あり |
次の値は
|
|
なし |
|
|
なし |
TimesTenでは、ユーザー定義オブジェクトはサポートされていません。 |
|
なし |
|
|
なし |
TimesTenでは、ユーザー定義オブジェクトはサポートされていません。 |
|
あり |
|
|
あり |
|
|
あり |
|
|
なし |
TimesTenでは、コレクションはサポートされていません。 |
|
なし |
|
|
なし |
|
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
なし |
|
|
なし |
|
|
あり |
記述子のサポートの詳細は、表3-4を参照してください。 |
|
あり |
SQL文ではサポートされていますが、PL/SQLではサポートされていません。 |
|
あり |
次の値は
|
|
なし |
|
|
なし |
|
|
あり |
PL/SQLオブジェクトはサポートされていません。 オブジェクトの記述は名前でのみサポートされます。
|
|
あり |
|
|
あり |
|
|
なし |
TimesTenではダイレクト・パス・ロードはサポートされていません。 |
|
あり |
LOBではサポートされています。期間の設定にかかわらず、期間はトランザクション存続期間を超えることはできません。 |
|
あり |
LOBではサポートされています。期間の設定にかかわらず、期間はトランザクション存続期間を超えることはできません。 |
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
あり |
次の値は
|
|
あり |
次の値は
注意: |
|
あり |
次の値は
|
|
あり |
|
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
あり |
|
|
あり |
|
|
あり |
次の値は
注意: |
|
あり |
記述子のサポートの詳細は、表3-4を参照してください。 |
|
なし |
TimesTenでは、コレクションはサポートされていません。 |
|
なし |
|
|
あり |
TimesTenでは、次を除く
注意:
|
|
あり |
|
|
あり |
|
|
あり |
|
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
なし |
TimesTenでは、データ・カートリッジはサポートされていません。 |
|
あり |
|
|
あり |
|
|
あり |
|
|
なし |
TimesTenでは、ユーザー定義オブジェクトはサポートされていません。 |
|
あり |
|
|
あり |
|
|
なし |
|
|
あり |
|
|
あり |
|
|
なし |
|
|
なし |
|
|
あり |
|
|
あり |
|
|
あり |
|
|
あり |
|
|
あり |
TimesTenでは、セッション間の切り替えはサポートされていません。 |
|
なし |
|
|
なし |
|
|
あり |
|
|
なし |
|
|
あり |
次の値は
注意: |
|
あり |
|
|
あり |
|
|
あり |
|
|
なし |
|
|
あり |
|
あり |
文のキャッシュについては、TimesTenでは、 |
|
|
あり |
文のキャッシングについては、TimesTenでは、文にタグを付けるための |
|
なし |
|
|
あり |
|
|
なし |
TimesTenでは、アドバンスト・キューイングはサポートされていません。 |
|
なし |
|
|
なし |
|
|
なし |
|
|
あり |
|
|
あり |
|
|
なし |
|
|
なし |
|
|
なし |
|
|
なし |
|
|
あり |
|
|
なし |
|
|
なし |
|
|
あり |
|
|
あり |
|
|
あり |
|
|
あり |
|
|
なし |
TimesTenでは、XML DBはサポートされていません。 |
|
なし |
TimesTenでは、XML DBはサポートされていません。 |
表3-3に、TimesTen OCIでサポートされているハンドルおよび属性を示します。
表3-3 TimesTen OCIでサポートされているハンドルおよび属性
ハンドル | Cオブジェクト | サポートされる属性 |
---|---|---|
環境 |
|
|
エラー |
|
|
サービス・コンテキスト |
|
|
文 |
|
|
バインド |
|
|
定義 |
|
|
記述 |
|
|
サーバー |
|
|
ユーザー・セッション |
|
|
認証 |
|
ユーザー・セッション・ハンドルの場合と同じです。 |
トランザクション |
|
|
スレッド |
|
表3-4に、TimesTen OCIでサポートされている記述子を示します。
表3-5に、TimesTen OCIでサポートされているSQLデータ型を示します。
表3-5 TimesTen OCIでサポートされているSQLデータ型
SQLデータ型 | 注意 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NCLOBに対する書込みおよび読取りを行うには、アプリケーション関数コールに対してキャラクタ・セット・フォーム( |
|
|
|
|
|
|
|
|
|
|
|
|
|
TimesTenには格納されていません。 |
|
TimesTenには格納されていません。 |
|
|
|
|
|
TimesTenに格納されるときに4MBで切り捨てられます。 |
|
TimesTenに格納されるときに4MBで切り捨てられます。 |
|
|
|
|
|
ROWIDはOracle Database形式で返されます。 |
|
1文につき1つの結果セット・パラメータのみが許可されます。 |
|
|
|
|
|
TimesTenに格納されるときにタイムゾーンは無視されます。 |
|
|
|
TimesTenに格納されるときにタイムゾーンは無視されます。 |
|
TimesTenに格納されるときにタイムゾーンは無視されます。 |
|
|
|
|
|
|
|
|
|
次の表3-6に、サポートされているパラメータ属性を示します。
表3-6 TimesTen OCIでサポートされているパラメータ属性
パラメータ | サポートされる属性 |
---|---|
すべてのパラメータ |
|
表およびビュー・パラメータ |
|
PL/SQLプロシージャおよび関数パラメータ |
|
PL/SQLサブプログラム・パラメータ |
|
PL/SQLパッケージ・パラメータ |
|
順序パラメータ |
|
列パラメータ |
|
引数および結果パラメータ |
|
リスト・パラメータ |
|
データベース・パラメータ |
|