ヘッダーをスキップ
Oracle® Objects for OLE開発者ガイド
11gリリース2 (11.2) for Microsoft Windows
B58887-04
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

4 OO4Oの拡張機能

この章では、Oracle Objects for OLEの拡張機能について説明します。内容は次のとおりです。

Oracleオブジェクト・リレーショナルとLOBデータ型のサポート

Oracle Objects for OLEは、REFのインスタンス、値インスタンス、可変長配列(VARRAY)、ネストした表およびOracleデータベースのラージ・オブジェクト(LOB)へのアクセスと操作をサポートしています。

表4-0に、Oracle Objects for OLEにおけるインスタンスのすべての型を示した階層図を示します。

図4-1 オブジェクト・リレーショナルとLOBデータ型のダイアグラム

OraFieldとOraParameterから始まるオブジェクト階層
「図4-1 オブジェクト・リレーショナルとLOBデータ型のダイアグラム」の説明

これらの型のインスタンスは、データベースからフェッチするか、またはストアド・プロシージャとファンクションを含めて、SQL文とPL/SQLブロックへの入力または出力変数として渡すことができます。すべてのインスタンスは、動的な属性アクセスと操作のためのメソッドを提供するCOMオートメーション・インタフェースにマップされます。これらのインタフェースの取得元は、次のとおりです。

  • ダイナセット内のOraFieldオブジェクトのValueプロパティ

  • SQL文またはPL/SQLブロックの入力または出力パラメータとして使用するOraParameterオブジェクトのValueプロパティ

  • 別のオブジェクト/REFインスタンスの属性

  • コレクション(VARRAYまたはネストした表)の要素

Oracle LOB、オブジェクトおよびコレクションのインスタンス化

Oracle Objects for OLEは、LOB、Oracleオブジェクトおよびコレクション型での作業用にCOMオートメーション・インタフェースを提供します。これらのインタフェースは、LOB、Oracleオブジェクトおよびコレクションのインスタンスに関連付けられているデータにアクセスするためのメソッドとプロパティを提供します。

Oracle LOB、オブジェクトおよびコレクション

表4-1に、OO4Oインタフェースに関連付けられているOracle LOB、オブジェクトおよびコレクション型を示します。

表4-1 Oracle LOB、オブジェクトおよびコレクション

OO4Oインタフェース

Object

OraObject

REF

OraRef

VARRAYとネストした表

OraCollection

BLOB

OraBlob

CLOB

OraClob

BFILE

OraBFile


前述のインタフェースがOO4Oで取り出される方法は、データベースに格納されている方法またはSQL文でアクセスされる方法によって異なります。可能な使用例を次に示します。

  • 表の列

    表に、LOB、オブジェクト型およびコレクションが列として含まれており、ダイナセットのSELECT文がこの表に基づいている場合、その列を表すOraFieldオブジェクトのValueプロパティは、その型に対応したOO4Oインタフェースを戻します。

  • SQL文またはPL/SQLブロックのバインド変数

    SQL文またはPL/SQLブロックに、バインド変数としてLOB、オブジェクト型およびコレクションがある場合は、Addメソッドを使用して対応するサーバー型でOraParameterオブジェクトを作成する必要があります。そのバインド変数を表すOraParameterオブジェクトのValueプロパティは、その型に対応したOO4Oインタフェースを戻します。

  • Oracleオブジェクト・インスタンスの属性

    Oracleオブジェクト・インスタンスにその属性としてLOB、オブジェクト型またはコレクションがある場合は、属性に対応するOO4Oインタフェースが、添字または属性の名前を使用してOraObjectまたはOraRefから取り出されるか、またはOraAttributeオブジェクトのValueプロパティを使用して取り出されます。

  • VARRAYとネストした表の要素

    OracleのVARRAYとネストした表に要素としてオブジェクト型とREFがある場合は、OraCollectionオブジェクトから要素の索引を添字として使用して、対応するOO4Oインタフェースが取り出されます。

これらの型に対するOO4Oインタフェースがダイナセットの一部として取り出される場合、OO4Oインタフェースは、そのダイナセットの現在の行のLOB、オブジェクトおよびコレクション型のインスタンスを表します。移動操作のために現在の行が変更されると、OO4Oインタフェースは、新しい現在の行のLOB、オブジェクトおよびコレクション型のインスタンスを表します。OraParameterの一部として前述の型のOO4Oインタフェースが取り出され、OraSQLStmtRefreshメソッドのためにOraParameterの値が変更されると、OO4Oインタフェースは、そのOraParameterに対する新しいインスタンスのLOB、オブジェクトおよびコレクション型を表します。

内部的には、OO4Oが各OraFieldOraParameterおよびOraAttributeオブジェクトに対して1つのOO4Oインタフェースを保持します。ダイナセットの移動操作、またはOraSQLStmtのリフレッシュ操作から独立して、LOB、オブジェクトおよびコレクション型のインスタンスを保持するには、対応するOO4OインタフェースでCloneメソッドを使用します。このメソッドは、LOB、オブジェクトおよびコレクション型インスタンスのコピーを作成し、そのコピーに関連付けられている対応のOO4Oインタフェースを戻します。

ラージ・オブジェクト(LOB)の使用

ラージ・オブジェクト(LOB)データ型(BLOBCLOBNCLOBおよびBFILE)によって、テキスト、イメージ、ビデオ・クリップおよびサウンドなどの非構造化データの大きなブロックを最高4GBまで格納できます。これらのデータ型は、効率のよいランダムでピース単位のデータ・アクセスを提供します。Oracle Objects for OLEでは、LOBデータ型のインスタンスはインタフェースとして表されます。


関連項目:


この項の内容は次のとおりです。

LOBデータ型

表4-2に、4つのLOBデータ型とそれに対応するOO4Oインタフェースを示します。

表4-2 LOBデータ型

LOBデータ型 LOBの値の構成データ 対応するOO4Oインタフェース

BLOB

非構造化バイナリ(RAW)データ。

OraBLOB

CLOB

シングルバイトの固定幅文字データ。Oracle Database用に定義されたデータベース・キャラクタ・セットに対応しています。

OraCLOB

NCLOB

マルチバイトの固定幅文字データ。Oracle Database用に定義された各国語キャラクタ・セットに対応しています。

OraCLOB

BFILE

ラージ・バイナリ・データがデータベース表領域以外のオペレーティング・システム・ファイルに格納されているLOB。BFILEは、ハード・ディスク、CD-ROM、Photo CD、DVDなどの3次的な記憶デバイスに配置することもできます。

OraBFILE


次の例では、OraDatabaseオブジェクトのExecuteSQLメソッドを使用して、BLOB列とCLOB列を保有する表を作成し、その表にいくつかの行を挿入します。

Set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
 
Set InvDb = OO4OSession.OpenDatabase("INVDB", "scott/tiger", 0) 
InvDb.ExecuteSQL("create table part(part_id NUMBER, part_name 
VARCHAR2(20),part_image BLOB, part_desc CLOB)") 
InvDb.ExecuteSQL ("insert into part values (1,'ORACLE NETWORK',EMPTY_BLOB()," & _
              "EMPTY_CLOB())") 
InvDb.ExecuteSQL ("insert into part values (2,'ORACLE SERVER', EMPTY_BLOB()," & _
           "EMPTY_CLOB())") 

EMPTY_BLOB()EMPTY_CLOB()は、LOB列に空のLOBを挿入するPL/SQLファンクションです。


関連項目:

ExecuteSQLメソッド

OraBLOBとOraCLOBの使用

OO4OのOraBLOBOraCLOBインタフェースは、BLOBCLOBNCLOBおよびBFILEのデータ型を含むデータベース内のラージ・オブジェクトに関する操作を実行するためのメソッドを提供します。

次のVisual Basicの例では、part表からPartImageを読み込む方法を示します。

Dim Buffer as Variant
Set Part = OraDatabase.CreateDynaset("select * from part", 0&)
set PartImage = OraDynaset.Fields("part_image").Value
 
'read the data into the buffer
amount_read = PartImage.Read(buffer)
 
'copy the image content into the file
PartImage.CopyToFile "d:\image\partimage.jpg"

データベースからのLOBの取出し

OraBlobOraClobおよびOraBFileオブジェクトは、OraDynasetオブジェクトまたはパラメータ・オブジェクトを使用して、取り出すことができます。

OraDynasetオブジェクトの使用

表にLOB列があり、ダイナセットの問合せがそのLOB列を選択している場合、OraFieldオブジェクトのValueプロパティは、OraBlobOraClobまたはOraBFileオブジェクトを戻します。次の例では、part表からLOB列を選択します。PartDescPartImageは、OraFieldオブジェクトから取り出したOraBlobOraClobオブジェクトです。

Set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
Set InvDb = OO4OSession.OpenDatabase("INVDB", "scott/tiger", 0) 
Set Part = InvDb.CreateDynaset("select * from part", 0&) 
Set PartDesc = Part.Fields("part_desc").Value 
Set PartImage = Part.Fields("part_image").Value 

パラメータ・オブジェクトの使用

SQL文またはPL/SQLブロックにLOB型のバインド変数がある場合は、OraParametersAddメソッドを使用してOraParameterオブジェクトを作成します。そのバインド変数に対するOraParameterオブジェクトのValueプロパティは、OraBlobOraClobまたはOraBFileオブジェクトを戻します。

次の例では、LOBデータ型をPL/SQLの無名ブロック内のバインド変数として使用する方法を示します。このブロックは、データベースからLOB列を選択します。

Set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
Set InvDb = OO4OSession.OpenDatabase("INVDB", "scott/tiger", 0) 
InvDb.Parameters.Add "PartDesc", Null, ORAPARM_OUTPUT,ORATYPE_CLOB 
InvDb.Parameters.Add "PartImage", Null, ORAPARM_OUTPUT,ORATYPE_BLOB 
InvDb.ExecuteSQL ("BEGIN select part_desc, part_image into :PARTDESC," & _
             ":PARTIMAGE from part where part_id = 1 for update NOWAIT; END;") & _
             "for update NOWAIT; END;") 
Set PartDesc = InvDb.Parameters("PartDesc").Value 
Set PartImage = InvDb.Parameters("PartImage").Value 

LOBの読取りと書込みに関するパフォーマンス上の考慮

アプリケーションのメモリー使用量を最適化してネットワーク・ラウンドトリップの回数を削減するために、LOBの読取りと書込みに関するオプションがいくつかあります。

単一ピース操作

1回のラウンドトリップで、バッファの内容がデータベースに読み書きされます。

複数ピース操作

複数のコールに対して1つの小さいバッファが使用され、メソッドが読み書きされます。このモードでは、読取りまたは書込みコールごとに1回のラウンドトリップが必要となるのではなく、データはストリーム化されます。この方法は、小規模な単一操作を複数回行うよりも高速です。これには、データを順に読み書きする必要があるため、各読取りまたは書込みに伴ってオフセットが自動的に増加するという制約があります。書込み前に合計量を知っておく必要があり、完了前に操作を中断することはできません。

LOBバッファリング・オプション

LOBバッファリング・オプションは、すべての読み書き操作を自動的にバッファリングします。ネットワーク・ラウンドトリップが発生するのは、FlushBufferメソッドがコールされた場合のみです。LOB全体にわたって小規模な書込みが多数発生する場合は、このオプションが最も有効です。このメソッドには大きな制限があります。

LOBデータの書込み

OraBlobOraClobオブジェクトのWriteメソッドは、ローカル・バッファからデータベースのLOBにデータを書き込みます。CopyFromFile(OraLOB)メソッドは、ローカル・ファイルの内容をデータベースのLOBに書き込みます。

Writeメソッドも含めてLOBの値を変更するすべての操作は、そのLOBに関連付けられている行がロックされているときにのみ発生します。また、LOBフィールドがNULLの場合は、メソッドが書き込む前にLOBフィールドを空のLOBで更新しておく必要があります。

次の各項で説明するように、LOBデータは、単一ピースまたは一連の複数ピースで書き込むことができます。

単一ピース書込み操作

1回のネットワーク・ラウンドトリップで、バッファの内容全体を単一ピースとして書き込むことができます。次の例では、ローカル・ファイルpartimage.datから10KBのデータをpart_image列のオフセット1000に書き込みます。

Dim buffer() as byte 
ReDim buffer(10000) 
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
Set InvDb = OO4OSession.OpenDatabase("INVDB", "scott/tiger", 0) 
Set Part = InvDb.CreateDynaset("select * from part", 0&) 
Set PartImage = Part.Fields("part_image").Value 
PartImage.Offset = 1000 
FNum = FreeFile 
Open "PartImage.Dat" For Binary As #FNum 
Get #FNum, , buffer 
Part.Edit 
 
amount_written = PartImage.Write(buffer) 
Part.Update 
Close FNum 

CopyFromFile(OraLOB)メソッドは、ローカル・ファイルからLOBに直接データを書き込みます。次のコードは、前述のコードと同じ機能を果たします。

Part.Edit 
PartImage.CopyFromFile "PartImage.dat" , 10000, 1000 
Part.Update 

複数ピース書込み操作

このメカニズムは、使用できるバッファのサイズが書込みデータ量の合計に満たない場合に使用します。書込みデータの合計量は、PollingAmount(OraLOB/BFILE)プロパティを使用して設定します。

Offset(OraLOB/BFILE)プロパティが使用されるのは、Write操作の最初のピースに対するオフセットを設定する際の1回のみです。1回目以降のオフセットは、前のピースのサイズ分だけ自動的に増分されます。各ピースのWrite操作が正常に終了したことをStatus(OraLOB/BFILE)プロパティで確認する必要があります。StatusプロパティがORALOB_NEED_DATAを戻した場合は、Writeメソッドを再度コールする必要があります。これは、PollingAmountプロパティで指定された量が送信されるまで継続する必要があります。

最初に送信するピースについてはWriteメソッドのpiecetype引数がORALOB_FIRST_PIECEに設定され、Write操作の最後のピースについてはpiecetype引数がORALOB_LAST_PIECEに設定されている必要があります。複数ピース操作の終了時点で、StatusプロパティはORALOB_NO_DATAを戻します。

次の例では、ローカル・ファイルpartimage.datから、102KBのデータを10KBのチャンクでpart_image列のオフセット1000に書き込みます。

Dim buffer() as byte 
chunksize = 10000 
ReDim buffer(chunksize) 
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
Set InvDb = OO4OSession.OpenDatabase("INVDB", "scott/tiger", 0) 
Set Part = InvDb.CreateDynaset("select * from part", 0&) 
Set PartImage = Part.Fields("part_image").Value 
 
FNum = FreeFile 
Open "PartImage.Dat" For Binary As #FNum 
PartImage.Offset = 1000 
PartImage.PollingAmount =102000 
remainder = 102000 
Part.Edit 
Get #FNum, , buffer 
amount_written = PartImage.Write(buffer, chunksize, ORALOB_FIRST_PIECE) 
 
While PartImage.Status = ORALOB_NEED_DATA 
remainder = remainder - chunksize 
If remainder < chunksize Then 
piecetype = ORALOB_LAST_PIECE 
chunksize = remainder 
 
Else 
piecetype = ORALOB_NEXT_PIECE 
End If 
Get #FNum, , buffer 
amount_written = PartImage.Write(buffer, chunksize, piecetype) 
Wend 
Close FNum 
Part.Update 

LOBデータの読込み

OraBlobOraClobReadメソッドは、データベースのLOBからローカル・バッファにデータを読み込みます。CopyFromFileメソッドは、LOBの内容をローカル・ファイルに読み込みます。

次の各項で説明するように、LOBデータは、単一ピースまたは一連の複数ピースで読み込むことができます。

単一ピース読込み操作

1回のネットワーク・ラウンドトリップで、バッファの内容全体を単一ピースとして読み込むことができます。次の例では、10KBのデータをpart_image列のオフセット1000からローカル・ファイルimage.datに読み込みます。

Dim buffer as Variant 
Dim buf() As Byte 
chunksize = 10000 
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
Set InvDb = OO4OSession.OpenDatabase("INVDB", "scott/tiger", 0) 
Set Part = InvDb.CreateDynaset("select * from part", 0&) 
Set PartImage = Part.Fields("part_image").Value 
FNum = FreeFile 
Open "image.dat" For Binary As #FNum 
PartImage.Offset = 1000 
amount_read = PartImage.Read(buffer,10000) 
buf = buffer 
Put #FNum, , buf 
Close FNum 

CopyToFile(OraLOB/BFILE)メソッドは、LOBからローカル・ファイルに直接データを書き込みます。次のコードは、前述のコードと同じ機能を果たします。

PartImage.CopyToFile "image.dat" , 10000, 1000 

複数ピース読込み操作

このメカニズムは、使用できるバッファのサイズが読込みデータ量の合計に満たない場合に使用します。読込みデータの合計量は、PollingAmount(OraLOB/BFILE)プロパティを使用して設定します。Offset(OraLOB/BFILE)プロパティが使用されるのは、Read操作の最初のピースに対するオフセットを設定する際の1回のみです。1回目以降のオフセットは、前のピースのサイズ分だけ自動的に増分されます。

各ピースのRead操作が正常に終了したことをStatus(OraLOB/BFILE)プロパティで確認する必要があります。StatusプロパティがORALOB_NEED_DATAを戻した場合は、Readメソッドを再度コールする必要があります。これは、PollingAmountプロパティで指定された量が読み込まれるまで継続する必要があります。複数ピース操作の終了時点で、StatusプロパティはORALOB_NO_DATAを戻します。

次の例では、part_image列のオフセット1000から、102KBのデータを10KBのチャンクでローカル・ファイルimage.datに読み込みます。

Dim buffer as Variant 
Dim buf() As Byte 
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
Set InvDb = OO4OSession.OpenDatabase("INVDB", "scott/tiger", 0) 
Set Part = InvDb.CreateDynaset("select * from part", 0&) 
Set PartImage = Part.Fields("part_image").Value 
FNum = FreeFile 
Open "image.dat" For Binary As #FNum 
PartImage.offset = 1000 
PartImage.PollingAmount = 102000 
amount_read = PartImage.Read(buffer, chunksize) 
buf = buffer 
Put #FNum, , buf 
While PartImage.Status = ORALOB_NEED_DATA 
amount_read = PartImage.Read(buffer, chunksize) 
buf = buffer 
Put #FNum, , buf 
Wend 
Close FNum 

Oracleオブジェクト・データ型

オブジェクト型は、データベースに作成されるユーザー定義による複合データ型です。オブジェクト型は列または行によって表すことができます。Object型のインスタンスは、データベースに格納できます。このオブジェクト・インスタンスは、クライアント側にフェッチし、Oracle Objects for OLEを使用して変更できます。


関連項目:

『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』

オブジェクト・インスタンスには2つの型があります。

  • OraObjectオブジェクト

    列がオブジェクト型を表す場合、このオブジェクト型のインスタンスは、埋込みインスタンスまたは値インスタンスとして参照されます。OO4Oでは、この型がOraObjectオブジェクトによって示されます。たとえば、ADDRESSオブジェクト型はPERSON表の列として格納されます。OraObjectオブジェクトは、他の構造体に埋め込むことができます。埋込みインスタンスまたは値インスタンスは、他のオブジェクト・インスタンスの属性となることもできます。

  • OraRefオブジェクト

    オブジェクト表にある行がオブジェクト型を表す場合、この型のインスタンスは参照可能オブジェクトとして参照されます。OO4Oでは、この型がOraRefオブジェクトによって示されます。内部的に参照可能なオブジェクトには、REFデータ型によって示される固有のオブジェクト識別子があります。REF列は、参照可能なオブジェクトへのポインタと考えることができます。OO4Oアプリケーションは、参照可能オブジェクトからREFデータ型を取り出し、関連付けられた参照可能オブジェクトをクライアント側にフェッチ(確保)し、変更済の参照可能オブジェクトをデータベースに更新(フラッシュ)できます。

OraObjectインタフェースの概要

OraObjectインタフェースは、Oracle埋込みオブジェクトまたは値インスタンスの表現形式です。これには、値インスタンスの個々の属性にアクセスおよび操作(更新および挿入)するためのコレクション・インタフェース(OraAttributes)が含まれます。

添字または属性名を使用すると、OraAttributesコレクション・インタフェースの個々の属性にアクセスできます。

次のVisual Basicの例では、person_tab表にあるAddressオブジェクトの属性にアクセスする方法を示します。

Set Person = OraDatabase.CreateDynaset("select * from person_tab",0&) 
set Address = Person.Fields("Addr").Value 
msgbox Address.Zip 
msgbox.Address.City 

OraObjectインタフェースの使用

次の例では、属性として通り、市、州および郵便番号を持つADDRESSオブジェクト型と、ADDRESSオブジェクト型の列があるPERSON表を作成します。また、ここでは、OraDatabaseオブジェクトのExecuteSQLメソッドを使用してデータを挿入します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
HRDb.ExecuteSQL("create type ADDRESS as object ( street 
VARCHAR2(200), city varchar2(20), state CHAR(2), zip varchar2(10) )")  
HRDb.ExecuteSQL("create table person (name varchar2(20), age number," & _ 
                 "addr ADDRESS) ") 
HRDb.ExecuteSQL("insert into person values('nasser',40, " & _
                 "address('Wine Blvd', 'Pleasanton', 'CA', '94065'))") 
HRDb.ExecuteSQL("insert into person values('Maha', 25," & _ 
                 "address('Continental Way', 'Belmont', 'CA', '94002'))")
HRDb.ExecuteSQL("insert into person values('chris',30, address('First " & _
                 "Street', 'San Francisco', 'CA' ,'94123'))") 

次の各項では、OraObjectインタフェースの操作について説明します。


関連項目:

ExecuteSQLメソッド

データベースからの埋込み/値インスタンスの取出し

ダイナセットまたはパラメータ・オブジェクトを使用してOO4Oを使用すると、OraObjectオブジェクトを取り出すことができます。

ダイナセット・オブジェクトの使用

表にオブジェクト型の列があり、ダイナセットの問合せでその列が選択されると、OraFieldオブジェクトのValueプロパティはOraObjectを戻します。

次のコードは、person表からADDRESS列を選択し、OraFieldオブジェクトからAddressオブジェクトを取り出します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
set Person = hrDb.CreateDynaset("select * from person", 0&) 
set Address = Person.Fields("Addr").Value 
パラメータ・オブジェクトの使用

SQL文またはPL/SQLブロックにオブジェクト型のバインド変数がある場合は、OraParametersAddメソッドを使用してOraParameterオブジェクトを作成します。そのバインド変数に対するOraParameterオブジェクトのValueプロパティは、OraObjectオブジェクトを戻します。

次の例では、オブジェクト・データ型をPL/SQLの無名ブロック内のバインド変数として使用します。このブロックは、データベースからオブジェクト列を選択します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
hrDb.Parameters.Add "ADDRESS", Null, ORAPARM_OUTPUT, ORATYPE_OBJECT, "ADDRESS"
'execute the sql statement which selects Address from the person_tab 
hrDb.ExecuteSQL ("BEGIN select Addr into :ADDRESS from person where " & _
            "age = 40; end;") 
'retrieve Address object from the OraParameter 
set address = hrDb.Parameters("ADDRESS").Value 

埋込み/値インスタンスの属性へのアクセス

添字または属性名を使用すると、個々の属性にアクセスできます。次の例では、ADDRESSオブジェクト・インスタンスの属性値にアクセスする方法を示します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
set Person = hrDb.CreateDynaset("select * from person", 0&) 
set Address = Person.Fields("Addr").Value 
msgbox Address.City 
msgbox Address.Street 
msgbox Address.State 
msgbox Address.Zip 

次のコードはすべての属性値にアクセスします。

For I=1 to Address.Count 
   msgbox Address(I) 
Next I 

埋込み/値インスタンスの属性の変更

オブジェクト・インスタンスがダイナセット・オブジェクトを使用して取り出された場合は、Dynaset Edit/Updateのペア間でその属性値を変更できます。次の例では、ADDRESSオブジェクト・インスタンスのstreetとcityの属性値を変更します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
set Person = hrDb.CreateDynaset("select * from person", 0&)
set Address = Person.Fields("Addr").Value
Person.Edit
      Address.Street  =  "Oracle Parkway"
      Address.City = "Redwood shores"
Person.Update

Oracleオブジェクト・インスタンスのメンバー・メソッドの実行

Oracleオブジェクト型のメンバー・メソッドは、型の作成中に作成されます。Oracleオブジェクト・インスタンスのメンバー・メソッドは、OO4OでPL/SQLプロシージャまたはファンクションとして実行されます。メンバー・メソッドに対する引数と戻り値は、OraParameterオブジェクトを使用してバインドされている必要があります。メンバー・メソッドに対する最初の引数は、常にオブジェクト・インスタンスです。このオブジェクト・インスタンスは、ORAPARM_INPUTまたはORAPARM_BOTHモードでバインドできます。メンバー・メソッドがオブジェクト・インスタンスの属性を変更する場合やOO4Oアプリケーションに新しいオブジェクト・インスタンスを取り出す必要がある場合、このオブジェクト・インスタンスは、ORAPARM_BOTHモードでバインドされる必要があります。

たとえば、bank_accountオブジェクト型にメンバー・メソッドとしてopencloseおよびdepositがある場合、bank_accountオブジェクト型のスキーマは次のとおりです。

CREATE OR REPLACE TYPE bank_account AS OBJECT ( 
    acct_number INTEGER(5), 
    balance REAL, 
    MEMBER PROCEDURE open (amount IN REAL), 
    MEMBER PROCEDURE close (num IN INTEGER, amount OUT REAL), 
    MEMBER PROCEDURE deposit (SELF IN OUT bank_bccount,num IN 
                        INTEGER, amount IN REAL), 
); 

OO4Oでは、BankObjはデータベースからの有効なbankオブジェクト・インスタンスを表すOraObjectオブジェクトです。depositメソッドを実行するには、OraParameterオブジェクトを使用して、SELFnumおよびamount引数をバインドする必要があります。

Dim BankObj as OraObject 
assumes that we have valid BankObj 
set BankObj = ..... 
 
'create a OraParameter object for bank_account object and set it to BankObj 
OraDatabase.Parameters.Add "BANK", BankObj, ORAPARM_BOTH, ORATYPE_OBJECT, _
                     "BANK_ACCOUNT" 
 
'create a OraParameter object for num argument and set the value to 100 
OraDatabase.Parameters.Add "ACCOUNT_NO", 100, ORAPARM_INPUT, ORATYPE_NUMBER 
 
'create a OraParameter object for amount argument and set the value to 1200 
OraDatabase.Parameters.Add "AMOUNT", 1200, ORAPARM_OUTPUT, ORATYPE_NUMBER
 
'display the balance from the bank object 
Bankobj.balance 
 
'now execute the PL/SQL block for member method execution 
OraDatabase.ExecuteSQL ("BEGIN BANK_ACCOUNT.DEPOSIT :BANK," & _ 
                    (":ACCOUNT_NO,:AMOUNT); END;") 
 
'get the modified bank object from the parameter 
set Bankobj  = OraDatabase.Parameters("BANK").Value 
 
'display the new balance 
Bankobj.balance 

OraRefインタフェースの概要

OraRefインタフェースは、クライアント・アプリケーション内の参照可能オブジェクト(REF)のインスタンスを表します。オブジェクトの属性は、OraObjectインタフェースが示すオブジェクトの属性にアクセスする場合と同じ方法でアクセスされます。OraRefインタフェースは、COMの包含機構を介してOraObjectインタフェースから導出されます。REFオブジェクトは、ダイナセットなど、その元のコンテキストとは関係なく更新および削除されます。また、OraRefインタフェースは、Oracle Call Interface(OCI)の複合オブジェクト検索機能(COR)を利用して、オブジェクトのグラフ全体をナビゲートする機能をカプセル化することもできます。


関連項目:

OraRefオブジェクト

OraRefインタフェースの使用

この項では、PERSON_TABという名前のオブジェクト表を作成します。このオブジェクト表はオブジェクト型PERSONOBJに基づいています。このオブジェクト表の行への各参照は、CUSTOMERS表のapersonというREF型の列に格納されています。次のコードは、データベース・スキーマを作成します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
HRDb.ExecuteSQL("create type PERSONOBJ  as object ( name varchar2(20), " & _
                 "age number, addr ADDRESS)")
HRDb.ExecuteSQL("create table person_tab of personobj") 
HRDb.ExecuteSQL("insert into person_tab values('nasser',40," & _ 
                  "address('Wine Blvd', 'Pleasanton', 'CA', '94065'))") 
HRDb.ExecuteSQL("insert into person_tab values('Maha', 25, " & _
                  "address('Continental Way', 'Belmont', 'CA', '94002'))") 
HRDb.ExecuteSQL("insert into person_tab values('chris',30, " & _
               "address('First Street', 'San Francisco', 'CA' , '94123'))") 

次のコードは、オブジェクト表の行を参照するapersonというREF列を持つCUSTOMERS表を作成します。

HRDb.ExecuteSQL("create table CUSTOMERS (account number, 
aperson REF personobj)") 
 
HRDb.ExecuteSQL("insert into customers values(10, null)") 
HRDb.ExecuteSQL("insert into customers values(20, null)") 
HRDb.ExecuteSQL("insert into customers values(30, null)") 
HRDb.ExecuteSQL("update customers set aperson = (select ref(p) from " & _
                 "person_tab p where p.name = 'nasser') where account = 10") 
HRDb.ExecuteSQL("update customers set aperson = (select ref(p) from " & _
                 "person_tab p where p.name = 'Maha') where account = 20") 
HRDb.ExecuteSQL("update customers set aperson = (select ref(p) from " & _
                 "person_tab p where p.name = 'chris') where account = 30") 

次の各項では、OraRefインタフェースの操作について説明します。


関連項目:

OraRefオブジェクト

データベースからのREFの取出し

OO4Oを次のように使用すると、OraRefオブジェクトを取り出すことができます。

ダイナセット・オブジェクトの使用

表にREF型の列があり、ダイナセットの問合せでその列が選択されると、OraFieldオブジェクトのValueプロパティはOraREFを戻します。次の例では、person表からaperson列を選択し、OraFieldオブジェクトからapersonオブジェクトを取り出します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
set Customer = hrDb.CreateDynaset("select * from customers", 0&) 
set Person = Customer.Fields("aperson").Value 
OraParameterオブジェクトの使用

SQL文またはPL/SQLブロックにREF型のバインド変数がある場合は、OraParametersAddメソッドを使用してOraParameterオブジェクトを作成します。そのバインド変数に対するOraParameterオブジェクトのValueプロパティは、OraREFを戻します。

次の例では、REFオブジェクト・データ型をPL/SQLの無名ブロック内のバインド変数として使用します。このブロックは、データベースからオブジェクト列を選択します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
hrDb.Parameters.Add "PERSON", Null, ORAPARM_OUTPUT, ORATYPE_REF,"PERSONOBJ"
 
'execute the sql statement which selects Address from the person_tab 
hrDb.ExecuteSQL ("BEGIN select aperson into :PERSON from customers" & _ 
                "where account = 10; end;") 
 
'retrieve Person object from the OraParameter 
set Person = hrDb.Parameters("PERSON").Value 

関連項目:

OraRefオブジェクト

参照可能なインスタンスの属性へのアクセス

参照可能なインスタンスの属性は、アクセスする前にクライアント側でフェッチ(確保)する必要があります。OO4Oは、OraRefオブジェクトから属性値にアクセスするとき、暗黙的にREF値を確保します。PIN操作の後、参照可能なインスタンスの属性は、OraObjectオブジェクトが示す値インスタンスの属性にアクセスする場合と同じ方法でアクセスされます。

次の例では、APERSONというREF値を(暗黙的に)確保して、そのname属性とaddress属性にアクセスします。address属性にアクセスすると、AddressというOraObjectオブジェクトを戻すことに注意してください。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
set Customer = hrDb.CreateDynaset("select * from customers", 0&) 
set Person = Customer.Fields("APERSON").Value 
msgbox Person.Name 
set Address = Person.Addr 
msgbox Address.City 

関連項目:

OraRefオブジェクト

参照可能なインスタンスの属性の変更

参照可能なインスタンスはオブジェクト表の行に格納されるため、参照可能なインスタンスの属性を変更するには、オブジェクト・ロックが必要です。そのため、オブジェクト表のオブジェクト・インスタンスに対応する行をロックする必要があり、これは、OraRefオブジェクトのEditメソッドをコールすることで実行できます。オブジェクト・ロックはOraRef Updateメソッドによって解除します。

次の例では、Personオブジェクトのage属性を変更します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
set Customer = hrDb.CreateDynaset("select * from customers", 0&) 
set Person = Customer.Fields("APERSON").Value 
Person.Edit 
Person.Age = 45 
Person.Update 

Oracleコレクション

コレクションとは、すべて同じ型の要素が順序付けされたグループです。各要素には、索引と呼ばれる固有の添字があり、コレクション内の位置を判断します。


注意:

OraCollection要素の索引は1から開始します。

コレクションは、次の型に細分化できます。

  • NESTED TABLE型

    データベース表の列に格納されている表として参照されます。ネストした表の行には、1で始まる連続した添字が割り当てられ、配列にアクセスする要領で、個々の行にアクセスして取り出します。

  • VARRAY

    データベース表の列に格納されている配列として参照されます。VARRAY型の要素を参照するには、標準的な添字構文を使用できます。たとえば、Grade(3)は、Gradesという名前のVARRAYで第3番目の要素を参照します。

Oracle Objects for OLEでは、OraCollectionインタフェースがOracleコレクション型を示します。詳細は、次の各項を参照してください。

OraCollectionインタフェースの概要

OraCollectionインタフェースは、Oracleコレクション型、つまりOO4Oの可変長配列(VARRAY)とネストした表にアクセスして操作するためのメソッドを提供します。コレクションに含まれる要素へのアクセスには、添字を使用します。

次のVisual Basicの例では、department表にあるEnameListオブジェクトの属性にアクセスする方法を示します。

Set Person = OraDatabase.CreateDynaset("select * from department",0&)
set EnameList = Department.Fields("Enames").Value
 
'access all elements of the EnameList VArray
for I=1 to I=EnameList.Size
   msgbox EnameList(I)
Next I

データベースからのコレクション型インスタンスの取出し

OO4Oを次のように使用すると、コレクション型を取り出すことができます。

ダイナセット・オブジェクトの使用

表にコレクション型の列があり、ダイナセットの問合せでその列が選択されると、OraFieldオブジェクトのValueプロパティはOraCollectionオブジェクトを戻します。

次の例では、department表からENAMES列を選択し、OraFieldオブジェクトからEnameListオブジェクトを取り出します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
Set Dept = hrDb.CreateDynaset("select * from department", 0&) 
Set EnameList = Dept.Fields("ENAMES").Value 

パラメータ・オブジェクトの使用

SQL文またはPL/SQLブロックにコレクション型のバインド変数がある場合は、OraParametersAddメソッドを使用してOraParameterオブジェクトを作成します。そのバインド変数に対するOraParameterオブジェクトのValueプロパティは、OraCollectionオブジェクトを戻します。

次の例では、コレクションのデータ型をPL/SQLの無名ブロック内のバインド変数として使用し、データベースからコレクション型を選択します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
hrDb.Parameters.Add "ENAMES", Null, ORAPARM_OUTPUT, ORATYPE_VARRAY, "ENAMELIST" 
hrDb.ExecuteSQL ("BEGIN select enames into :ENAMES from department" & _ 
              "where dept_id = 10; END;") 
set EnameList = hrDb.Parameters("ENAMES").Value 

コレクションの要素へのアクセス

個々の要素の値には、添字を使用してアクセスします。たとえば、添字1に対してOraCollectionオブジェクトが戻すValueは、索引1にある要素の値です。添字の最大値は、削除した要素も含めたコレクションの要素の総数と同じです。OraCollectionの添字は、1から開始します。

次のコード例では、Enamelistコレクション・インスタンスを取り出し、第1索引と第2索引の要素にアクセスします。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
Set Dept = hrDb.CreateDynaset("select * from department", 0&) 
Set EnameList = Dept.Fields("ENAMES").Value 
msgbox EnameList(1) 
msgbox EnameList(2) 

次のコードは、EnameListコレクションの要素の値をすべて表示します。

For I = 1 to EnameList.Size 
   msgbox EnameList(I) 
Next I 

コレクションの要素の変更

コレクション・インスタンスがダイナセット・オブジェクトを使用して取り出された場合は、Dynaset Edit/Updateのペア間で要素の値を変更できます。次のコード例では、Enamelistコレクション・インスタンスの2番目の要素値を変更します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
 
Set OraDynaset = hrDb.CreateDynaset("select * from department", 0&) 
Set EnameList = OraDynaset.Fields("ENAMES").Value 
 
OraDynaset.Edit 
    EnameList(2) = "Chris" 
OraDynaset.Update 

VARRAYコレクション型の作成

次のコード例では、VARRAYコレクション型のENAMELISTと、ENAMELISTコレクション型の列を含んだdepartment表を作成します。

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set hrDb = OO4OSession.OpenDatabase("Exampledb", "scott/tiger", 0)
hrDb.ExecuteSQL("CREATE TYPE ENAMELIST AS VARRAY(20) OF VARCHAR2(30)") 
hrDb.ExecuteSQL("CREATE TABLE department (dept_id NUMBER(2),name" & _ 
               "VARCHAR2(15),ENAMES ENAMELIST)") 

次のスクリプトは、department表にいくつかのコレクション・データを挿入します。

hrDb.ExecuteSQL("INSERT INTO department VALUES(10, 'ACCOUNTING'," & _ 
               "ENAMELIST('KING','CLARK','MILLER') )") 
hrDb.ExecuteSQL("INSERT INTO department VALUES(20, 'RESEARCH'," & _ 
               "ENAMELIST('JONES','SCOTT','ADAMS','SMITH','FORD') )") 
hrDb.ExecuteSQL("INSERT INTO department VALUES(30, 'SALES'," & _ 
               "ENAMELIST('BLAKE','MARTIN','ALLEN','TURNER','JAMES') )")

OraCollectionオブジェクトからのダイナセットの作成

SQLのTHEまたはTABLE演算子を使用すると、VARRAYおよびネストした表のコレクション型のインスタンスに対してSELECT問合せが発行され、個々の要素に行としてアクセスできます。これらのコレクション型の要素の型はオブジェクト型で、オブジェクト型の個々の属性は行のフィールドを示します。

たとえば、Xというオブジェクト型にa、bおよびcの属性があり、コレクションの要素の型がXというオブジェクト型の場合は、このコレクションのSELECT問合せによってa、bおよびcのフィールドが戻ります。

OO4Oでは、コレクションのSELECT問合せによって、読取り専用のダイナセット・オブジェクトが作成されます。個々の要素には、行ナビゲーションを使用してアクセスします。コレクション型にその要素の型としてオブジェクト型がある場合、そのオブジェクト型(要素)の属性には、OraFieldオブジェクトを使用してアクセスします。

たとえば、Courseというオブジェクト型があり、CourseListというネストした表のコレクション型にその要素の型としてCourseがある場合は、次のように記述します。

CREATE TYPE Course AS OBJECT ( 
    course_no NUMBER(4), 
    title VARCHAR2(35), 
    credits NUMBER(1) 
); 
CREATE TYPE CourseList AS TABLE OF Course;

OO4Oでは、CourseListというOraCollectionは、CourseListコレクション型のインスタンスを表します。

Dim CourseList as OraCollection 

有効なCourseListコレクション・インスタンスがあると仮定します。

set CourseList = ...... 

SQLのTHEまたはTABLE演算子には、バインド変数としてコレクション型が必要です。CourseListというOraCollectionに対するOraParameterオブジェクトを作成します。

OraDatabase.Parameters.Add "COURSELIST", CourseList, ORAPARM_INPUT, _
            ORATYPE_TABLE, "COURSELIST" 

SQLのTHE演算子を使用し、CourseListに基づいて読取り専用のダイナセットを作成します。

Set CourseListDyn = OraDatabase.CreateDynaset("select * from THE (select" & _
           "CAST(:COURSELIST AS COURSELIST) from dual)", ORADYN_READONLY)

または、SQLのTABLE演算子を使用し、CourseListに基づいて読取り専用のダイナセットを作成します。この方法は、Oracle9i リリース以降のライブラリを使用するOO4Oでのみ使用できます。

Set CourseListDyn = OraDatabase.CreateDynaset("select * from" & _
          "TABLE(CAST(:COURSELIST AS COURSELIST))", ORADYN_READONLY) 

'display the course_no field 
msgbox CourseListDyn.Fields("course_no").Value 

'display the title field 
msgbox CourseListDyn.Fields("title").Value 

'move to next row 
OraDynaset.MoveNext 

例: OraCollectionオブジェクトからのダイナセットの作成

次の例では、OraCollectionオブジェクトからダイナセットを作成する方法を示します。サンプル・コードを実行する前に、必要なデータ型と表がデータベース内にあることを確認してください。「OraCollectionの例で使用されているスキーマ・オブジェクト」を参照してください。

Dim OraSession as OraSession 
Dim OraDatabase as OraDatabase 
Dim OraDynaset as OraDynaset 
Dim CourseList as OraCollection 
Dim Course as OraObject 
Dim CourseListDyn as OraDynaset 
 
'create the OraSession Object. 
Set OraSession = CreateObject("OracleInProcServer.XOraSession") 
 
'create the OraDatabase Object by opening a connection to Oracle. 
Set OraDatabase = OraSession.OpenDatabase("ExampleDb", "scott/tiger",  0&) 
 
'create a dynaset object from division 
set OraDynaset = OraDatabase.CreateDynaset("select * from division", 0&) 
 
'retrieve a Courses column from Division. Here Value property 
'of OraField object 'returns CourseList OraCollection 
set CourseList = OraDynaset.Fields("Courses").Value 
 
'create a input parameter for CourseList for nested table dynaset 
OraDatabase.Parameters.Add "COURSELIST", CourseList, ORAPARM_INPUT, _
                 ORATYPE_TABLE, "COURSELIST" 
 
'create a read only dynaset based on the CourseList. 
Set CourseListDyn = OraDatabase.CreateDynaset("select * from" & _ 
                 "THE(select CAST(:COURSELIST AS COURSELIST) from dual)", _
                 ORADYN_READONLY) 
 
'dynaset can also be created from Oracle8 collection using the
'following statement 
'Set CourseListDyn = OraDatabase.CreateDynaset("select * from    
'TABLE(CAST(:COURSELIST AS COURSELIST))", ORADYN_READONLY) 

'get the field values of the collection dynaset 
msgbox CourseListDyn.Fields("title").Value 
msgbox CourseListDyn.Fields("course_no").Value 
 
'move the original dynaset to second row 
Oradynaset.MoveNext 
 
'set the new value of CourseList  collection from the second row 
'of main dynaset to the "COURSELIST" parameter 
OraDatabase.Parameters("COURSELIST").Value = CourseList 
 
'refresh the collection dynaset. Now the collection dynaset values are refreshed 
'with new collection value. CourseListDyn.Refresh 
'get the field values of the collection dynaset 
msgbox CourseListDyn.Fields("title").Value 
msgbox CourseListDyn.Fields("course_no").Value 

アドバンスト・キューイング・インタフェース

Oracle Objects for OLEは、OraAQオートメーション・インタフェースに、メッセージをキューおよびデキューするためのメソッドを提供します。OraAQMsgオブジェクトには、エンキューまたはデキューするメッセージが含まれます。このメッセージは、RAWメッセージまたはユーザー定義型の場合があります。

次の例では、DBQというキューからRAWメッセージをエンキューする方法を示します。DBQキューは、すでにデータベース内に作成済であることが必要です。

Dim Q as OraAQ 
Dim Msg as OraAQMsg 
set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set empDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 
Set Q = empDb.CreateAQ("DBQ") 
Retrieve the message object from the Q object. 
set Msg = Q.AQMsg 
Specify the message value. 
Msg.Value = "This is the first Test message" 
Enqueue the message. 
Q.Enqueue 

次の行は、優先順位の高いメッセージをエンキューします。

Msg.Priority = ORAQMSG_HIGH_PRIORITY 
Msg.Delay = 5 
Msg.Value = "Urgent message" 
Q.Enqueue 

次の例では、Oracle DatabaseからRAWメッセージをデキューしてメッセージの内容を表示します。

Q.Dequeue 
MsgBox Msg.value 
Dequeue and display the first high priority message 
Msg.Priority = ORAQMSG_HIGH_PRIORITY 
Q.Dequeue 
MsgBox Msg.value 

関連項目:

OraAQオブジェクト

メッセージの監視

OraAQの監視メソッド(MonitorStartおよびMonitorStop)は、通知による非同期デキューを提供します。これは、非ブロック・モードでメッセージを処理するアプリケーションに適しています。アプリケーションは、Monitorメソッドにオートメーション・オブジェクトを指定することによって、メッセージの到着通知を要求できます。このオブジェクトは、NotifyMeというメソッドを実装して通知を受信します。メッセージは、コンシューマ名、メッセージIDまたは相関に基づいて監視できます。

次のサンプル・コードでは、この機能の簡単な使用方法を示します。これは、指値注文で売買を実行する、コンピュータによる株取引システムを表します。

このサンプルでは、STOCKS_TO_TRADEキュー用のキュー・オブジェクトをインスタンス化し、コンシューマBROKER_AGENT向けのメッセージを監視します。STOCKS_TO_TRADEは、TRADEORDER_TYPEというユーザー定義型のメッセージをキューします。これによって、売買注文の開始に必要なすべての情報がカプセル化されます。宛先がBROKER_AGENTのメッセージがデキューされると、CallbackClientオブジェクトのNotifyMeメソッドがコールされ、株の売買が実行されます。

'First instantiate the CallbackClient. The queue monitor 
' will invoke the NotifyMe on this class module.
Public CB_Client As New CallbackClient 
 
  Dim DB As OraDatabase
  Dim Q as OraAQ
  set Q = DB.CreateAQ("STOCKS_TO_TRADE") 

'Notify by calling cbclient::NotifyMe when there are messages
' for consumer '"BROKER_AGENT"
  Q.consumer = "BROKER_AGENT"

'Note that cbclient is a dispatch interface that supports the NotifyMe method.
  Dim s as string
  s = "BROKER_AGENT"
 'Notify the client only when there are messages for "BROKER_AGENT"
  Q.MonitorStart CB_Client, Q, s, 1
'other processing is performed here... 
 
  Q.MonitorStop 
Return 
'Now implement the NotifyMe method of the CallbackClient class module
'and the necessary arguments that will contain the dequeued message
'NotifyMe is the callback interface defined by user. Ctx here is the
'Q object passed in at the time of MontiorStart.
Public sub NotifyMe (ByVal Ctx As Variant, ByVal Msgid As Variant )
  On Error GoTo NotifyMeErr
  Dim tradingSignal as OraAQMsg
  'Tradeorder contains details of the customer order
  Dim tradeorder as OraObject
  If IsNull(Msgid) Then
          MsgBox "No Message"
          'Get Error
          MsgBox OraDatabase.LastServerErrText
  Else
          mvarMsgid = Msgid
          Set tradingSignal = Ctx.AQMsg(1,"STOCK_TYPE","TRADER")
          set tradeorder = tradingSignal.Value

          'Tradeorder is the object of UDT "STOCK_TYPE"Access signal attribute 
          'of tradeorder as tradeorder("signal).Value or tradeorder!signal
          if (tradeorder!signal = "SELL")
            'Sell the stock
             SellStock(tradeorder!NoOfShares, tradeorder!Ticker, _
                    tradeorder!Price,  tradeorder!ValidUntil)
          else if (tradeorder!signal = "BUY")
             'Buy the stock
              BuyStock(tradeorder!NoOfShares,tradeorder!Ticker, _
                   tradeorder!Price,tradeorder!ValidUntil)
          end if
  End If
NotifyMeErr:
  Call RaiseError(MyUnhandledError, "newcallback:NotifyMe Method")
End Sub

データベース・イベント

Oracle Databaseでは、データベース・イベントの検出および実行時の発行がサポートされています。

データベース・イベントの発行機能によって、他のアプリケーションからのメッセージをサブスクライブする場合と同じように、アプリケーションはデータベース・イベントをサブスクライブできます。

ユーザーは、次のイベントの発行を可能にできます。

  • DMLイベント(DELETEINSERTUPDATE)

  • DDLイベント(CREATEALTERDROP)

  • データベース・イベント(SERVERERRORLOGONLOGOFFSTARTUPSHUTDOWN)

イベントの発行サブシステムは、AQのパブリッシュ/サブスクライブ・エンジンに統合されています。


関連項目:

データおよびシステム・イベントのトリガーの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。


Oracle Objects for OLEには、COMユーザーによるOracle Databaseイベントのサブスクライブを可能にする機能が用意されています。

この機能では、関心のあるサブスクライバに対するデータベース・イベントの非同期通知がサポートされています。このモデルでは、クライアントは、サブスクリプションとして格納された各要求について、データベースまたはシステム・イベントが通知されるようにサブスクライブできます。

関心のあるデータベース・イベントが発生すると、データベース・イベント・ハンドラによってサブスクライバに通知されます。イベント・ハンドラは、イベントのサブスクリプション時に登録されています。

OO4Oでは、データベース・イベントへのサブスクリプションを表すOraSubscriptionオブジェクト、およびOraSubscriptionオブジェクトのリストを維持するOraSubscriptionsコレクションを提供しています。

データベース・イベントをサブスクライブするには、次の操作が必要です。

  • 関心があるデータベース・イベントに基づいて、サブスクリプションを作成します。

  • データベース・イベント・ハンドラを指定します。データベース・イベント・ハンドラは、NotifyDBEventsメソッドを実装するオートメーション・オブジェクトであることが必要です。NotifyDBEventsメソッドは、サブスクライブされたデータベース・イベントが発生すると、OO4Oによってコールされます。

  • Registerメソッドを使用してサブスクリプションを登録します。

例: データベース・イベントが通知されるようにアプリケーションを登録する方法

次の例では、アプリケーションが、データベース・ログイン・イベント(データベースへのすべてのログインなど)の通知をサブスクライブします。ユーザーがデータベースにログインすると、サブスクリプション時に渡されたDBEventsHdlrNotifyDBEventsメソッドがコールされます。コンテキスト依存の情報およびイベント固有の情報がNotifyDBEventsメソッドに渡されます。

この例のDBEventsHdlrは、後で定義されるDBEventClsです。

メイン・アプリケーションは次のとおりです。

' First instantiate the dbevent handler. The dbevent notification
' will fire the NotifyDBEvents on the callback handler.
 
Public DBEventsHdlr As New DBEventCls
Private Sub Form_Load()
    Dim gOraSession As Object
    Dim gOraSubscriptions As OraSubscriptions 
    Dim gOraDatabase As OraDatabase
 
    'Create the OraSession Object
    Set gOraSession = CreateObject("OracleInProcServer.XOraSession")
 
   'Create the OraDatabase Object by opening a connection to Oracle.
    Set gOraDatabase = gOraSession.DbOpenDatabase                      
             ("ora90.us.oracle.com", "pubsub/pubsub", 
              ORADB_ENLIST_FOR_CALLBACK)
    Set gOraSubscriptions = gOraDatabase.Subscriptions
    gOraSubscriptions.Add "PUBSUB.LOGON:ADMIN", DBEventsHdlr,
             gOraDatabase
    gOraSubscriptions(0).Register
    MsgBox "OK"
End Sub

NotifyDBEventsメソッドを定義するデータベース・イベント・ハンドラ・クラスは次のとおりです。

Public countofMsgs as integer
Public Function NotifyDBEvents(Ctx As Variant, Payload As Variant )
    On error goto NotifyMeErr
 
    MsgBox "Retrieved payload " + Payload
   ' do something - here the subscription is unregistered after
   ' receiving 3 notifications
    countofMsgs = countofMsgs + 1
    If countofMsgs > 3 Then
        Ctx.Subscriptions(0).UnRegister
    End If
    Exit Sub
NotifyMeErr:
    Call RaiseError(MyUnhandledError, "newcallback:NotifyMe Method")
 
End Sub

関連項目:


アプリケーション・フェイルオーバー通知

一方のデータベース・インスタンスが失敗したためにもう一方のインスタンスにフェイルオーバーする場合は、アプリケーション・フェイルオーバー通知を使用できます。フェイルオーバー中に遅延が発生する可能性があるため、アプリケーション開発者は、ユーザーに対して、フェイルオーバーを実行中であることを知らせてスタンバイするように求める必要があります。また、初期インスタンスのセッションがALTER SESSIONコマンドを受け取っている可能性もあります。これらのコマンドは、2番目のインスタンスで自動的に再実行されるわけではありません。そのため、開発者はこれらのALTER SESSIONコマンドを2番目のインスタンスで再実行する必要があります。

フェイルオーバー通知の登録

前述の問題を解決するために、OO4Oはアプリケーション・フェイルオーバー通知をサポートしています。フェイルオーバー通知を受信するには、通知ハンドラがOraDatabaseオブジェクトのMonitorForFailoverメソッドに登録されている必要があります。通知ハンドラは、OnFailoverメソッドを実装するオートメーション・オブジェクト(Visual Basicのクラス・モジュール)であることが必要です。フェイルオーバー通知の登録時に、このオートメーション・オブジェクトへのIDispatchポインタをクライアント固有のコンテキストとともに渡してください。

フェイルオーバーの際には、ユーザー・セッションを再度確立する過程でOnFailoverメソッドが何度かコールされます。通知ハンドラのOnFailoverメソッドが最初にコールされるのは、インスタンスの接続が失われていることをデータベースが最初に検出したときです。これは、遅延の発生をアプリケーションからユーザーに伝えることができるようにするためです。フェイルオーバーが成功した場合は、接続が再度確立されて使用可能になると、OnFailoverメソッドの2回目のコールが発生します。このときに、クライアントはALTER SESSIONコマンドを再実行し、フェイルオーバーが行われたことをユーザーに知らせる必要があります。

フェイルオーバーに失敗した場合は、OnFailoverメソッドがコールされ、フェイルオーバーが行われないことをアプリケーションに知らせます。

フェイルオーバーの登録の例は、次の項にある例に含まれています。


関連項目:


フェイルオーバーの有効化

フェイルオーバー通知を有効にするには、OpenDatabaseメソッドのコールに、ORADB_ENLIST_FOR_CALLBACKを渡す必要があります。


関連項目:

OpenDatabaseメソッド

例: フェイルオーバー通知

次のサンプルでは、開発者が定義した一般的なOnFailover実装を示し、アプリケーションの登録方法を説明します。

'Implement the OnFailover method of the FailoverClient class module and the 
' necessary arguments that will contain the dequeued message. Ctx  here is
' the application-defined context sensitive object that was passed
' in while registering with MonitorForFailover.
' An error of OO4O_FO_ERROR indicates that failover was unsuccessful, but the 
' application can handle the and retry failover by returning  
' a value of OO4O_FO_RETRY 
 
Public Function OnFailover(Ctx As Variant, fo_type As Variant,fo_event _
                     as variant, fo_OraDB as Variant) 
Dim str As String 

OnFailover=0 
str = Switch(fo_type = 1&, "NONE", fo_type = 2&, "SESSION", fo_type = _ 
                  4&, "SELECT") 
If IsNull(str) Then 
   str = "UNKNOWN!" 
End If 
If fo_event= OO4O_FO_ERROR Then 
   MsgBox "Failover error gotten. Retrying " 
   OnFailover = OO4O_FO_RETRY 
   End If 
If fo_event = OO4O_FO_BEGIN Then 
   MsgBox " Failing Over .... with failover type : " & str 
Else 
   MsgBox "Failover Called with event : " & fo_event 
End If 
End Function 

フェイルオーバー通知を受信するためのアプリケーションの登録

' First instantiate the Failover_Client. The Failover notification 
' will invoke the OnFailover on this class module 
 
Public Failover_Client As New FailoverClient 
Dim OraDatabase As OraDatabase 
Dim OraSession As OraSession 
Set OraSession = CreateObject("OracleInProcServer.XOraSession") 
 
' Pass in the entire database name (ie., the entire Tnsnames entry 
' with the domain name)in the opendatabase call 
Set OraDatabase = OraSession.DbOpenDatabase("Exampledb.us.oracle.com", _ 
          "scott/tiger", ORADB_ENLIST_FOR_CALLBACK) 
OraDatabase.MonitorForFailover Failover_Client, OraDatabase

XMLの生成

Oracle Objects for OLEのXMLのサポートによって、Oracleデータベースから、データをXML形式で抽出することが可能です。

XML形式のデータは、XMLをサポートする他のソフトウェアのコンポーネントに統合できます。XMLドキュメントはWebサーバーでスタイルシートとともに提供されるため、データの内容と表示を分離し、検索を容易にするためにデータをネイティブの構成で保つことができます。

eXtensible Stylesheet Language Transformations(XSLT)を使用して、開発者は他の業務から受け取ったXMLドキュメントを、各業務で必要なスタイルに再フォーマットできます。

XMLの詳細は、次のサイトを参照してください。

http://www.w3.org/XML/

XMLの生成の例

OO4Oでは、開始する行番号と、その後に続く指定の行数に基づいて、任意のOraDynasetメソッドの内容からXMLを表現します。次に、例を示します。

OO4Oコード

Dim XMLString As String 
Dim startrow as Integer 
Dim maxrows as Integer 
Set OraSession = CreateObject("OracleInProcServer.XOraSession") 
Set OraDatabase = OraSession.OpenDatabase("ExampleDb", "scott/tiger", 0&) 
Set OraDynaset = OraDatabase.CreateDynaset("select EMPNO, ENAME, COMM, JOB " & _
           "from  EMP", 0&) 
startrow = 4 
maxrows = 2 
 
'Output at most 2 rows beginning at row 4 
XMLString = OraDynaset.GetXML(startrow, maxrows) 

XML出力

<?xml version = "1.0"?> 
<ROWSET> 
<ROW id="4"> 
<EMPNO>7566</EMPNO> 
<ENAME>JONES</ENAME> 
<JOB>MANAGER</JOB> 
</ROW> 
<ROW id="5"> 
<EMPNO>7654</EMPNO> 
<ENAME>MARTIN</ENAME> 
<COMM>1400</COMM> 
<JOB>SALESMAN</JOB> 
</ROW> 
</ROWSET> 

XMLの書式は、OraDynasetおよびOraFieldのメソッドを使用してカスタマイズできます。

Dim XMLString As String 
Dim startrow as Integer 
Dim maxrows as Integer 
Set OraSession = CreateObject("OracleInProcServer.XOraSession") 
Set OraDatabase = OraSession.OpenDatabase("ExampleDb", "scott/tiger", 0&) 
Set OraDynaset = OraDatabase.CreateDynaset("select EMPNO, ENAME, COMM," & _ 
            "JOB from EMP", 0&)  
 
'Change the root tag of the XML document 
OraDynaset.XMLRowsetTag = "ALL_EMPLOYEES" 
 
'Change the row tag of the XML document 
OraDynaset.XMLRowTag = "EMPLOYEE" 
 
'Remove the rowid attribute 
OraDynaset.XMLRowID = "" 
 
'Turn on the null indicator 
OraDynaset.XMLNullIndicator = True 
 
'Change the EMPNO tag name 
Set EmpnoField = OraDynaset.Fields("EMPNO") 
EmpnoField.XMLTagName = "EMP_ID" 
 
'and make it an attribute rather than an element 
EmpnoField.XMLAsAttribute = True 
 
'Change the ENAME tag name 
Set EnameField = OraDynaset.Fields("ENAME") 
EnameField.XMLTagName = "NAME" 
 
'Change the COMM tag name 
Set CommField = OraDynaset.Fields("COMM") 
CommField.XMLTagName = "COMMISSION" 
 
'Change the JOB tag name 
Set JobField = OraDynaset.Fields("JOB") 
JobField.XMLTagName = "JOB_TITLE" 
startrow = 4 
maxrows = 2 
 
'Output at most 2 rows beginning at row 4 
XMLString = OraDynaset.GetXML(startrow, maxrows) 

出力

<?xml version = "1.0"?> 
<ALL_EMPLOYEES> 
<EMPLOYEE EMP_ID="7566"> 
<NAME>JONES</NAME> 
<COMMISSION NULL="TRUE"></COMMISSION> 
<JOB_TITLE>MANAGER</JOB_TITLE> 
</EMPLOYEE> 
<EMPLOYEE EMP_ID="7654"> 
<NAME NULL>MARTIN</NAME> 
<COMMISSION>1400</COMMISSION> 
<JOB_TITLE>SALESMAN</JOB_TITLE> 
</EMPLOYEE> 
</ALL_EMPLOYEES> 

日時および間隔のデータ型

リリース9.2.0.4以降では、OO4Oで提供される4つの新規オブジェクトを使用すると、開発者は、Oracle9iで導入された新規日時および期間データ型にアクセスしたり操作できます。表4-3に、OO4Oオブジェクトおよび対応するデータ型を説明します。

表4-3 日時および間隔のデータ型

OO4Oオブジェクト Oracleデータ型

OraIntervalDS

INTERVAL DAY TO SECOND

OraIntervalYM

INTERVAL YEAR TO MONTH

OraTimeStamp

OraTimeStamp

TIMESTAMP

TIMESTAMP WITH LOCAL TIME ZONE

OraTimeStampTZ

TIME WITH TIME ZONE


これらの型のインスタンスは、データベースからフェッチするか、またはストアド・プロシージャとファンクションを含めて、SQL文とPL/SQLブロックへの入力または出力変数として渡すことができます。

これらの新しいデータ型は、PL/SQL索引付き表、VARRAY、ネストした表などのコレクションの要素としてはサポートされていません。

日時および間隔のデータ型の取得

OO4Oの日時および間隔のデータ型は、次の方法で取得できます。

  • ダイナセット内のOraFieldオブジェクトのValueプロパティ

  • SQL文またはPL/SQLブロックの入力または出力パラメータとして使用するOraParameterオブジェクトのValueプロパティ

  • 別のオブジェクトまたはREFの属性

  • 次のOraSessionメソッド

    • CreateOraIntervalDS

    • CreateOraIntervalYM

    • CreateOraTimeStamp

    • CreateOraTimeStampTZ

日時および間隔のデータ型の説明

  • OraTimeStampオブジェクト

    Oracle TIMESTAMPまたはTIMESTAMP WITH LOCAL TIME ZONEデータ型に関する操作を行うためのメソッドを提供します。操作には、日時値へのアクセスと日時操作の実行が含まれます。

  • OraTimeStampTZオブジェクト

    Oracle TIMESTAMP WITH TIME ZONEデータ型に関する操作を行うためのメソッドを提供します。操作には、日時やタイムゾーンの値へのアクセスと日時操作の実行が含まれます。

  • OraIntervalDSオブジェクト

    Oracle INTERVAL DAY TO SECONDに関する操作を行うためのメソッドを提供します。このデータ型は、期間を日数、時間、分、秒およびナノ秒で表します。

  • OraIntervalYMオブジェクト

    Oracle INTERVAL YEAR TO MONTHに関する操作を行うためのメソッドを提供します。このデータ型は、期間を年数および月数で表します。

データベース・スキーマ・オブジェクト

OraMetaDataインタフェースにより、データベース・オブジェクトのスキーマ情報にアクセスできます。これは、OraDatabaseインタフェースのDescribeメソッドを起動すると、戻されます。Describeメソッドは、emp表などのスキーマ・オブジェクトの名前を取得して、OraMetaDataオブジェクトを戻します。OraMetaDataオブジェクトは、記述されているスキーマ・オブジェクトのすべての属性(OraMDAttributeコレクション)に動的にナビゲートおよびアクセスするメソッドを提供します。

次のVisual Basicスクリプトは、OraMetaDataインタフェースの簡単な使用例です。ここでは、emp表のいくつかの属性を取り出して表示します。

Dim empMD as OraMetaData 

set OO4OSession = CreateObject("OracleInProcServer.XOraSession") 
set empDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0) 

'Add EMPNO as an Input parameter and set its initial value. 
Set empMd = empDb.Describe("emp")
 
'Get the column attribute collections. 
Set empColumnsMd = empMd("ColumnList").Value 

'Display name, data type, and size of each column in the emp table. 
For I = 0 To empColumnsMd.Count - 1 
   Set ColumnMd = empColumnsMd(I).Value 
   MsgBox ColumnMd("data type").Value 
   MsgBox ColumnMd("Name").Value 
Next I