この章では、Oracle Objects for OLEの拡張機能について説明します。内容は次のとおりです。
Oracle Objects for OLEは、REFのインスタンス、値インスタンス、可変長配列(VARRAY
)、ネストした表およびOracleデータベースのラージ・オブジェクト(LOB)へのアクセスと操作をサポートしています。
表4-0に、Oracle Objects for OLEにおけるインスタンスのすべての型を示した階層図を示します。
これらの型のインスタンスは、データベースからフェッチするか、またはストアド・プロシージャとファンクションを含めて、SQL文とPL/SQLブロックへの入力または出力変数として渡すことができます。すべてのインスタンスは、動的な属性アクセスと操作のためのメソッドを提供するCOMオートメーション・インタフェースにマップされます。これらのインタフェースの取得元は、次のとおりです。
ダイナセット内のOraField
オブジェクトのValue
プロパティ
SQL文またはPL/SQLブロックの入力または出力パラメータとして使用するOraParameter
オブジェクトのValue
プロパティ
別のオブジェクト/REF
インスタンスの属性
コレクション(VARRAY
またはネストした表)の要素
Oracle Objects for OLEは、LOB、Oracleオブジェクトおよびコレクション型での作業用にCOMオートメーション・インタフェースを提供します。これらのインタフェースは、LOB、Oracleオブジェクトおよびコレクションのインスタンスに関連付けられているデータにアクセスするためのメソッドとプロパティを提供します。
表4-1に、OO4Oインタフェースに関連付けられているOracle LOB、オブジェクトおよびコレクション型を示します。
表4-1 Oracle LOB、オブジェクトおよびコレクション
型 | OO4Oインタフェース |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
前述のインタフェースが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インタフェースが取り出され、OraSQLStmt
のRefresh
メソッドのためにOraParameter
の値が変更されると、OO4Oインタフェースは、そのOraParameter
に対する新しいインスタンスのLOB、オブジェクトおよびコレクション型を表します。
内部的には、OO4Oが各OraField
、OraParameter
およびOraAttribute
オブジェクトに対して1つのOO4Oインタフェースを保持します。ダイナセットの移動操作、またはOraSQLStmt
のリフレッシュ操作から独立して、LOB、オブジェクトおよびコレクション型のインスタンスを保持するには、対応するOO4OインタフェースでClone
メソッドを使用します。このメソッドは、LOB、オブジェクトおよびコレクション型インスタンスのコピーを作成し、そのコピーに関連付けられている対応のOO4Oインタフェースを戻します。
ラージ・オブジェクト(LOB)データ型(BLOB
、CLOB
、NCLOB
およびBFILE
)によって、テキスト、イメージ、ビデオ・クリップおよびサウンドなどの非構造化データの大きなブロックを最高4GBまで格納できます。これらのデータ型は、効率のよいランダムでピース単位のデータ・アクセスを提供します。Oracle Objects for OLEでは、LOBデータ型のインスタンスはインタフェースとして表されます。
この項の内容は次のとおりです。
表4-2に、4つのLOBデータ型とそれに対応するOO4Oインタフェースを示します。
表4-2 LOBデータ型
LOBデータ型 | LOBの値の構成データ | 対応するOO4Oインタフェース |
---|---|---|
|
非構造化バイナリ(RAW)データ。 |
|
|
シングルバイトの固定幅文字データ。Oracle Database用に定義されたデータベース・キャラクタ・セットに対応しています。 |
|
|
マルチバイトの固定幅文字データ。Oracle Database用に定義された各国語キャラクタ・セットに対応しています。 |
|
|
ラージ・バイナリ・データがデータベース表領域以外のオペレーティング・システム・ファイルに格納されているLOB。 |
|
次の例では、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ファンクションです。
OO4OのOraBLOB
とOraCLOB
インタフェースは、BLOB
、CLOB
、NCLOB
および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"
OraBlob
、OraClob
およびOraBFile
オブジェクトは、OraDynaset
オブジェクトまたはパラメータ・オブジェクトを使用して、取り出すことができます。
表にLOB列があり、ダイナセットの問合せがそのLOB列を選択している場合、OraField
オブジェクトのValue
プロパティは、OraBlob
、OraClob
またはOraBFile
オブジェクトを戻します。次の例では、part
表からLOB列を選択します。PartDesc
とPartImage
は、OraField
オブジェクトから取り出したOraBlob
とOraClob
オブジェクトです。
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型のバインド変数がある場合は、OraParameters
のAdd
メソッドを使用してOraParameter
オブジェクトを作成します。そのバインド変数に対するOraParameter
オブジェクトのValue
プロパティは、OraBlob
、OraClob
または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の読取りと書込みに関するオプションがいくつかあります。
複数のコールに対して1つの小さいバッファが使用され、メソッドが読み書きされます。このモードでは、読取りまたは書込みコールごとに1回のラウンドトリップが必要となるのではなく、データはストリーム化されます。この方法は、小規模な単一操作を複数回行うよりも高速です。これには、データを順に読み書きする必要があるため、各読取りまたは書込みに伴ってオフセットが自動的に増加するという制約があります。書込み前に合計量を知っておく必要があり、完了前に操作を中断することはできません。
OraBlob
とOraClob
オブジェクトの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
OraBlob
とOraClob
のRead
メソッドは、データベースの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
オブジェクト型は、データベースに作成されるユーザー定義による複合データ型です。オブジェクト型は列または行によって表すことができます。Object
型のインスタンスは、データベースに格納できます。このオブジェクト・インスタンスは、クライアント側にフェッチし、Oracle Objects for OLEを使用して変更できます。
関連項目: 『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』 |
オブジェクト・インスタンスには2つの型があります。
OraObject
オブジェクト
列がオブジェクト型を表す場合、このオブジェクト型のインスタンスは、埋込みインスタンスまたは値インスタンスとして参照されます。OO4Oでは、この型がOraObject
オブジェクトによって示されます。たとえば、ADDRESS
オブジェクト型はPERSON
表の列として格納されます。OraObject
オブジェクトは、他の構造体に埋め込むことができます。埋込みインスタンスまたは値インスタンスは、他のオブジェクト・インスタンスの属性となることもできます。
OraRef
オブジェクト
オブジェクト表にある行がオブジェクト型を表す場合、この型のインスタンスは参照可能オブジェクトとして参照されます。OO4Oでは、この型がOraRef
オブジェクトによって示されます。内部的に参照可能なオブジェクトには、REF
データ型によって示される固有のオブジェクト識別子があります。REF
列は、参照可能なオブジェクトへのポインタと考えることができます。OO4Oアプリケーションは、参照可能オブジェクトからREF
データ型を取り出し、関連付けられた参照可能オブジェクトをクライアント側にフェッチ(確保)し、変更済の参照可能オブジェクトをデータベースに更新(フラッシュ)できます。
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
次の例では、属性として通り、市、州および郵便番号を持つ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
インタフェースの操作について説明します。
ダイナセットまたはパラメータ・オブジェクトを使用して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ブロックにオブジェクト型のバインド変数がある場合は、OraParameters
のAdd
メソッドを使用して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オブジェクト・インスタンスのメンバー・メソッドは、OO4OでPL/SQLプロシージャまたはファンクションとして実行されます。メンバー・メソッドに対する引数と戻り値は、OraParameter
オブジェクトを使用してバインドされている必要があります。メンバー・メソッドに対する最初の引数は、常にオブジェクト・インスタンスです。このオブジェクト・インスタンスは、ORAPARM_INPUT
またはORAPARM_BOTH
モードでバインドできます。メンバー・メソッドがオブジェクト・インスタンスの属性を変更する場合やOO4Oアプリケーションに新しいオブジェクト・インスタンスを取り出す必要がある場合、このオブジェクト・インスタンスは、ORAPARM_BOTH
モードでバインドされる必要があります。
たとえば、bank_account
オブジェクト型にメンバー・メソッドとしてopen
、close
および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
オブジェクトを使用して、SELF
、num
および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
インタフェースは、クライアント・アプリケーション内の参照可能オブジェクト(REF
)のインスタンスを表します。オブジェクトの属性は、OraObject
インタフェースが示すオブジェクトの属性にアクセスする場合と同じ方法でアクセスされます。OraRef
インタフェースは、COMの包含機構を介してOraObject
インタフェースから導出されます。REF
オブジェクトは、ダイナセットなど、その元のコンテキストとは関係なく更新および削除されます。また、OraRef
インタフェースは、Oracle Call Interface(OCI)の複合オブジェクト検索機能(COR)を利用して、オブジェクトのグラフ全体をナビゲートする機能をカプセル化することもできます。
この項では、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
インタフェースの操作について説明します。
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
SQL文またはPL/SQLブロックにREF
型のバインド変数がある場合は、OraParameters
のAdd
メソッドを使用して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
参照可能なインスタンスの属性は、アクセスする前にクライアント側でフェッチ(確保)する必要があります。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
オブジェクトの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
コレクションとは、すべて同じ型の要素が順序付けされたグループです。各要素には、索引と呼ばれる固有の添字があり、コレクション内の位置を判断します。
注意: OraCollection 要素の索引は1 から開始します。 |
コレクションは、次の型に細分化できます。
NESTED TABLE型
データベース表の列に格納されている表として参照されます。ネストした表の行には、1で始まる連続した添字が割り当てられ、配列にアクセスする要領で、個々の行にアクセスして取り出します。
VARRAY
型
データベース表の列に格納されている配列として参照されます。VARRAY
型の要素を参照するには、標準的な添字構文を使用できます。たとえば、Grade(3)
は、Grades
という名前のVARRAY
で第3番目の要素を参照します。
Oracle Objects for OLEでは、OraCollection
インタフェースがOracleコレクション型を示します。詳細は、次の各項を参照してください。
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ブロックにコレクション型のバインド変数がある場合は、OraParameters
のAdd
メソッドを使用して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
コレクション型の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') )")
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
の監視メソッド(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イベント(DELETE
、INSERT
、UPDATE
)
DDLイベント(CREATE
、ALTER
、DROP
)
データベース・イベント(SERVERERROR
、LOGON
、LOGOFF
、STARTUP
、SHUTDOWN
)
イベントの発行サブシステムは、AQのパブリッシュ/サブスクライブ・エンジンに統合されています。
関連項目: データおよびシステム・イベントのトリガーの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
Oracle Objects for OLEには、COMユーザーによるOracle Databaseイベントのサブスクライブを可能にする機能が用意されています。
この機能では、関心のあるサブスクライバに対するデータベース・イベントの非同期通知がサポートされています。このモデルでは、クライアントは、サブスクリプションとして格納された各要求について、データベースまたはシステム・イベントが通知されるようにサブスクライブできます。
関心のあるデータベース・イベントが発生すると、データベース・イベント・ハンドラによってサブスクライバに通知されます。イベント・ハンドラは、イベントのサブスクリプション時に登録されています。
OO4Oでは、データベース・イベントへのサブスクリプションを表すOraSubscription
オブジェクト、およびOraSubscription
オブジェクトのリストを維持するOraSubscriptions
コレクションを提供しています。
データベース・イベントをサブスクライブするには、次の操作が必要です。
関心があるデータベース・イベントに基づいて、サブスクリプションを作成します。
データベース・イベント・ハンドラを指定します。データベース・イベント・ハンドラは、NotifyDBEvents
メソッドを実装するオートメーション・オブジェクトであることが必要です。NotifyDBEvents
メソッドは、サブスクライブされたデータベース・イベントが発生すると、OO4Oによってコールされます。
Register
メソッドを使用してサブスクリプションを登録します。
例: データベース・イベントが通知されるようにアプリケーションを登録する方法
次の例では、アプリケーションが、データベース・ログイン・イベント(データベースへのすべてのログインなど)の通知をサブスクライブします。ユーザーがデータベースにログインすると、サブスクリプション時に渡されたDBEventsHdlr
のNotifyDBEvents
メソッドがコールされます。コンテキスト依存の情報およびイベント固有の情報が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
を渡す必要があります。
例: フェイルオーバー通知
次のサンプルでは、開発者が定義した一般的な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
Oracle Objects for OLEのXMLのサポートによって、Oracleデータベースから、データをXML形式で抽出することが可能です。
XML形式のデータは、XMLをサポートする他のソフトウェアのコンポーネントに統合できます。XMLドキュメントはWebサーバーでスタイルシートとともに提供されるため、データの内容と表示を分離し、検索を容易にするためにデータをネイティブの構成で保つことができます。
eXtensible Stylesheet Language Transformations(XSLT)を使用して、開発者は他の業務から受け取ったXMLドキュメントを、各業務で必要なスタイルに再フォーマットできます。
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データ型 |
---|---|
|
|
|
|
|
|
|
|
これらの型のインスタンスは、データベースからフェッチするか、またはストアド・プロシージャとファンクションを含めて、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