この章では、Oracle Objects for OLEの基本的な機能について説明します。
内容は次のとおりです。
Oracle Objects for OLEを使用すると、クライアント・アプリケーションでは、Oracleデータベースに接続して各種コマンドを実行し、戻された結果にアクセスして操作できます。特定のタスクの実行順序には多少の柔軟性はありますが、OO4Oのオートメーション・オブジェクトを使用する各アプリケーションでは、次の基本的な手順を実行します。
サーバーからの切断および使用したOO4Oオブジェクトの解放
OO4Oオートメーション・サーバーを使用してOracleデータベースに接続するには、最初にサーバーのインスタンスを作成する必要があります。Visual Basic(VB)の場合、NEW
キーワードを使用することもできますが、通常はCreateObject
メソッドをコールすることでインスタンスを作成します。
Visual BasicのCreateObject
メソッドは、次の2つのOO4Oサーバー・オブジェクトとともに使用できます。次のいずれかのオブジェクトのインタフェースによって、OO4Oへのアクセスが提供され、Oracle Databaseへの接続が可能になります。
OraSession
アプリケーションの最高レベルのオブジェクトです。これは、OraDatabase
、OraConnection
およびOraDynaset
オブジェクトのコレクションを管理します。
OraServer
データベース・インスタンスへの物理的な接続を表し、接続多重化の使用が可能になります。
CreateObject
メソッドは、コンポーネントとオブジェクトのID
を引数として使用します。
次のスクリプトでは、Visual BasicでのOraSession
オブジェクトの取得方法を示します。OO4OSession
は、OraSession
オブジェクトのインスタンスを保持するオブジェクト変数です。
Dim OO4OSession as Object Set OO4OSession = CreateObject(“OracleInProcServer.XOraSession")
または
Dim OO4OSession as OraSession Set OO4OSession = New OraSessionClass
または
Dim OO4OSession as New OraSessionClass
次の例では、IIS Active Server PagesでのOraSession
オブジェクトの取得方法を示します。
<OBJECT RUNAT=Server SCOPE=APPLICATION ID=OO4OSession PROGID="OracleInProcServer.XOraSession"> </OBJECT>
OracleInProcServer.XOraSession
は、Oracleクライアント・インストール・プログラムがWindowsレジストリに登録する、バージョンに依存しないOO4OのプログラムID
です。これは、OO4Oコンポーネントを識別するグローバル一意識別子(CLSID
)のシンボリック名です。
インタフェースを取得した後は、そのインタフェースを使用してOpenDatabase
メソッドをコールし、Oracleデータベースにユーザー・セッションを確立できます。
Set EmpDb= OO4OSession.OpenDatabase("ExampleDb", "Scott/Tiger", 0)
または
Set EmpDb= OO4OServer.OpenDatabase("Scott/Tiger")
変数EmpDb
はユーザー・セッションを表します。これはOraDatabase
インタフェースを保持し、ネットワーク接続別名にExampleDb
を使用し、ユーザー名とパスワードにscott
/tiger
を使用して、Oracle Databaseにコマンドを送信します。
OraServer
インタフェースを使用すると、複数のユーザー・セッションでデータベースへの物理的なネットワーク接続を共有できます。これによって、ネットワークとデータベースのリソース使用量が削減されるため、サーバーの拡張性が向上します。ただし、複数のユーザー・セッションによるコマンド実行は、接続上でシリアル化されます。したがって、この機能は、パフォーマンス上の理由からコマンドのパラレル実行が必要なマルチスレッド・アプリケーションで使用することはお薦めしません。
次のコード例では、OraServer
インタフェースを使用して2つのユーザー・セッションを確立する方法を示します。
Set OO4OServer = CreateObject("OracleInProcServer.XOraServer")
OO4OServer.Open("ExampleDb")
Set EmpDb1 = OO4OServer.OpenDatabase("Scott/Tiger")
Set EmpDb2 = OO4OServer.OpenDatabase("Scott/Tiger")
ユーザー・セッションは、以前に作成したオブジェクトのプールから取得することもできます。
OO4Oオートメーション・オブジェクトを使用して、Oracleデータベースに送信できるコマンドは、次のカテゴリに分類されます。
問合せとは、データベースからデータを取り出す文です。1つの問合せで、0行、1行または複数行のデータを戻すことができます。すべての問合せは、次の例のようにSQLキーワードのSELECT
で始まります。
SELECT ename, empno FROM emp
OO4Oでは、このようなSELECT
文は、OraDatabase
インタフェースのCreateDynaset
メソッドと一緒に使用されることで問合せを実行します。このメソッドは、戻された行セットにアクセスして操作するために使用されるOraDynaset
オブジェクトを戻します。OraDynaset
オブジェクトは、実行した問合せによって戻された行セットの参照を可能にする、(前方および後方に)スクロール可能なクライアント側カーソルの機能をカプセル化します。
注意: 後方へのスクロールが不要な場合は、クライアントのローカル・ディスクにおける結果セットのキャッシュを使用禁止にできます。パフォーマンスの大幅な向上につながるため使用禁止にすることをお薦めします。CreateDynaset メソッドにORADYN_NOCACHE オプションを渡すと、キャッシュが使用禁止になります。この定数は、oraconst.txt ファイルに定義されており、OO4Oがインストールされているルート・ディレクトリORACLE_BASE\\ORACLE_HOME \OO4O にあります。 |
次のコード例では、ExampleDb
データベースに接続して問合せを実行し、行の結果セットを移動して、単純なメッセージ・ボックスに各行の列値を表示する方法を示します。
Set OO4OSession = CreateObject(“OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "Scott/Tiger", 0 )
' SELECT query described above used in next line
Set Employees = EmpDb.CreateDynaset("SELECT ename, empno FROM" & _
"emp",ORADYN_NOCACHE)
While NOT Employees.EOF
MsgBox "Name: " & Employees("ENAME").value & "Employee #: " & _
Employees("EMPNO").value
Employees.MoveNext
Wend
この例にあるEmployees
("ENAME"
)とEmployees
("EMPNO"
)は、結果セットの現在の行からENAME
列とEMPNO
列の値をそれぞれ戻します。列値にアクセスする他の方法は、ENAME
列にEmployees(0)
、EMPNO
列にEmployee(1)
のように、列の位置を使用する方法です。この方法によって、名前で列を参照するよりも速く列の値を取得できます。
この例のEmployees.MoveNext
文は、結果セットの現在の行を次の行に設定します。結果セットの最終行より後ろに移動しようとすると、OraDynaset
のEOF
プロパティがTRUE
に設定されます。
MoveNext
メソッドは、OraDynaset
インタフェース内のナビゲーショナル・メソッドの1つです。ナビゲーショナル・メソッドには、MoveFirst
、MoveLast
、MoveNext
、MovePrevious
、MoveNextn
、MovePreviousn
、MoveRel
およびMoveTo
があります。
OraDynaset
オブジェクトは、更新可能な実表またはビューから取り出した行を更新および削除するメソッドも提供しています。さらに、新しい行を挿入する方法も提供しています。「OraDynasetオブジェクト」を参照してください。
問合せでは、次の例のように、入力(バインド)変数を使用して、データベースにデータを提供するプログラムも要求できます。
SELECT name, empno FROM employees WHERE ename = :ENAME
このSQL文で、:ENAME
はアプリケーションが提供する変数のプレースホルダです。
OO4Oでは、OraParameter
オブジェクトを使用して、プレースホルダにデータ値を提供します。
パラメータを定義するには、OraParameters
コレクション・オブジェクトを使用します。このオブジェクトは、OraDatabase
インタフェースのParameters
プロパティを参照することによって取得します。OraParameters
コレクションは、OraParameter
オブジェクトへの参照を追加、削除および取得するためのメソッドを提供します。
次の文は、EmpDb
オブジェクト内のOraParameters
コレクションに入力パラメータのORAPARM_INPUT
を追加します。
EmpDb.Parameters.Add "ENAME", "JONES", ORAPARM_INPUT
ENAME
はパラメータ名で、SQL文のプレースホルダの名前と同じ(前述のサンプル・コードの:ENAME
)であることが必要です。初期値としてJONES
が指定され、ORAPARM_INPUT
はINPUT
パラメータとして使用されたことをOO4Oに通知します。
次の例では、'JONES'
という名前の従業員を含んだ1行のみのOraDynaset
オブジェクトを作成します。
Set OO4OSession = CreateObject(“OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "Scott/Tiger", 0 )
EmpDb.Parameters.Add "ENAME", "JONES", ORAPARM_INPUT
Set Employees = EmpDb.CreateDynaset("SELECT ename, empno FROM emp" & _
"WHERE ename = :ENAME",ORADYN_NOCACHE)
While NOT Employees.EOF
MsgBox "Name: " & Employees("ename").value & "Employee #: " & _
Employees("empno").value
Employees.MoveNext
Wend
データ操作言語(DML)文では、データベース表のデータを変更できます。たとえば、次のような操作にDML文が使用されます。
OO4OのOraDatabase
インタフェースは、DML文を実行するための2つのメソッド、ExecuteSQL
とCreateSQL
を提供します。次の説明には、これらのメソッドを様々なタイプのDML文の実行に使用する方法が記載されています。
次の例では、ExecuteSQL
メソッドを使用してUPDATE
文を実行します。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
EmpDb.Parameters.Add "ENAME", "JONES", ORAPARM_INPUT
EmpDb.ExecuteSQL ("UPDATE emp SET sal = sal + 1000 WHERE ename = :ENAME")
UPDATE
文の実行には、CreateSQL
メソッドを使用する方法もあります。
Set sqlStatement = EmpDb.CreateSQL("UPDATE emp SET sal = sal + 1000" & _ "WHERE ename = :ENAME", 0&)
ExecuteSQL
とCreateSQL
メソッドは両方とも、提供されたUPDATE文を実行します。異なる点は、CreateSQL
メソッドでは文の実行に加えOraSQLStmt
インタフェースへの参照を戻すことです。このインタフェースは、後でRefresh
メソッドを使用して同じ問合せを実行するときに使用できます。この問合せはすでにデータベースで解析されているため、後に続く同じ問合せの実行が、特にバインド・パラメータを使用した場合に高速化されます。
たとえば、名前がKING
という従業員の給与を1000増加するには、プレースホルダの値を変更し、sqlStatement
オブジェクトを次のようにリフレッシュします。
EmpDb.Parameters("ENAME").Value = "KING" sqlStatement.Refresh
頻繁に実行されるDML文の場合は、ExecuteSql
文を反復して使用するよりも、OraSqlStmt
オブジェクトにパラメータを使用する方が効率的です。OraSQLStmt
のRefresh
メソッドが実行されると、データベースによる文の解析は不要になります。異なるパラメータ値を持つ同じ問合せが頻繁に実行される、Webサーバーなどのアプリケーション・サーバーでは、前述の方法によってOracle Databaseの処理を大幅に軽減できます。
次の例では、CreateSQL
メソッドを使用してemp
表から行を削除します。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
EmpDb.Parameters.Add "ENAME", "JONES", ORAPARM_INPUT
Set sqlStatement = EmpDb.CreateSQL ("DELETE from emp WHERE ename = :ENAME")
emp
表から別の行を削除するには、パラメータの値を変更してsqlStatement
オブジェクトをリフレッシュします。
EmpDb.Parameters("ENAME").Value = "KING" sqlStatement.Refresh
次の例では、表に新しい行を追加します。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
EmpDb.ExecuteSQL ("INSERT INTO emp (empno, ename, job, mgr, deptno)" & _
"VALUES (1233,'OERTEL', 'WRITER', 7839, 30) ")
パラメータ配列を使用した複数行の挿入
パラメータ配列を使用すると、表内の複数行をフェッチ、更新、挿入または削除できます。パラメータ配列を使用した複数行の操作は、行を個別に操作する文を複数回にわたって実行するより効率的です。
次の例では、パラメータ配列の作成にOraDatabase
インタフェースのAddTable
メソッドを使用する方法を示します。配列には値が移入されており、emp
表に2つの行を挿入するINSERT
文の実行ではプレースホルダとして使用されます。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("Exampledb", "scott/tiger", 0)
'Creates parameter arrays for the empno, ename, job, and salary columns
EmpDb.Parameters.AddTable "EMPNO_ARRAY", ORAPARM_INPUT, ORATYPE_NUMBER, 2
EmpDb.Parameters.AddTable "ENAME_ARRAY", ORAPARM_INPUT, ORATYPE_VARCHAR2, 2, 10
EmpDb.Parameters.AddTable "JOB_ARRAY", ORAPARM_INPUT, ORATYPE_VARCHAR2, 2, 9
EmpDb.Parameters.AddTable "MGR_ARRAY", ORAPARM_INPUT, ORATYPE_NUMBER, 2
EmpDb.Parameters.AddTable "DEPT_ARRAY", ORAPARM_INPUT, ORATYPE_VARCHAR2, 2, 10
Set EmpnoArray = EmpDb.Parameters("EMPNO_ARRAY")
Set EnameArray = EmpDb.Parameters("ENAME_ARRAY")
Set JobArray = EmpDb.Parameters("JOB_ARRAY")
Set MgrArray = EmpDb.Parameters("MGR_ARRAY")
Set DeptArray = EmpDb.Parameters("DEPT_ARRAY")
'Populate the arrays with values
EmpnoArray(0) = 1234
EnameArray(0) = "JORDAN"
JobArray(0) = "SALESMAN"
MgrArray(0) = 7839
DeptArray(0) = 30
EmpnoArray(1) = 1235
EnameArray(1) = "YOUNG"
JobArray(1) = "SALESMAN"
MgrArray(1) = 7839
DeptArray(1) = 30
'Insert two rows
EmpDb.ExecuteSQL ("INSERT INTO emp (empno, ename, job, mgr, deptno) VALUES" & _
"(:EMPNO_ARRAY,:ENAME_ARRAY, :JOB_ARRAY,:MGR_ARRAY, :DEPT_ARRAY)")
OO4Oはスレッド・セーフであるため、マルチスレッドのアプリケーションおよびMicrosoft Internet Information Server(IIS)などの環境で効果的に使用できます。OO4Oは、COM/DCOM環境でのフリー・スレッドとアパートメント・スレッドの両モデルをサポートします。
OO4Oオブジェクト属性へのアクセスは、複数のスレッドを使用して実行されるとシリアル化されます。マルチスレッド・アプリケーションでの問合せ実行で最大の並列性をOO4Oで達成するには、複数スレッドでのオブジェクト共有を回避してください。
複数のスレッド間で共有されているセッション・オブジェクトで、コミット操作およびロールバック操作を使用することを避けてください(そのセッションと関連付けられているすべての接続がコミットまたはロールバックされるため)。セッション・オブジェクトでコミット操作およびロールバック操作を実行するには、使用するデータベース・オブジェクトごとに一意のセッション・オブジェクトを作成します。
OO4Oの接続プールは、OraDatabase
オブジェクトのプールです。OO4Oの接続プールは、(多くの場合)すでに接続しているOraDatabase
オブジェクトのグループです。データベースとの間で接続と切断を繰り返す必要のあるアプリケーション(ASP Webアプリケーションなど)の場合は、接続プールを使用するとパフォーマンスが向上します。
接続プールは、OraSession
インタフェースのCreateDatabasePool
メソッドをコールすることによって作成されます。OraDatabase
オブジェクトは、Oracleデータベースへの接続を表し、SQL文とPL/SQLブロックを実行するためのメソッドを含んでいます。
プールからOraDatabase
オブジェクトを取リ出すには、GetDatabaseFromPool
メソッドをコールします。このファンクションは、OraDatabase
オブジェクトへの参照を戻します。
プールが属している親セッション・オブジェクトが破棄されると、そのプールも暗黙的に破棄されます。DestroyDatabasePool
メソッドをコールすることにより、いつでも明示的に破棄できます。
リリース8.1.6以上のクライアントにリンクされたOO4Oは、失われた接続の検出をサポートします。
OraDatabase
オブジェクトのConnectionOK
プロパティをコールすることで、データベース接続の状態をアプリケーションで検証できます。OraSession.GetDatabaseFromPool
メソッドは、アプリケーションにOraDatabase
を戻す前に、接続を検証するようになりました。
接続が失われている場合、GetDatabaseFromPool
メソッドはその接続を削除し、新しい接続をフェッチします。
Dim MyDatabase As OraDatabase
Set MySession = CreateObject("OracleInProcServer.XOraSession")
Set MyDatabase = MySession.OpenDatabase("ora90", "scott/tiger", 0&)
' Other code
...
' Check if the database connection has not timed out
if MyDatabase.ConnectionOK
MsgBox " The database connection is valid"
endif
PL/SQLは、SQLを拡張したOracleの手続き型言語です。PL/SQLは、単純な問合せやSQLのデータ操作言語文では実行できない複雑なタスクを処理します。PL/SQLがない場合、Oracle Databaseでは、SQL文を1回に1文ずつ処理する必要があります。各SQL文ではデータベースに対して別のコールが発生するため、パフォーマンス上のオーバーヘッドが高くなります。ネットワーク環境では、このオーバーヘッドが大きな負担となる可能性があります。SQL文が発行されるたびに、ネットワークを介してSQL文を送信する必要があるため、通信量が増加します。PL/SQLでは、複数文のブロック全体をデータベースに1回で送信できます。これによって、アプリケーションとデータベース間での通信量を大幅に削減できます。
PL/SQLでは、多数の構造体を1ブロックにグループ化し、1つの単位として実行できます。次の内容が含まれています。
1つ以上のSQL文
変数宣言
代入文
プロシージャ制御文(IF...THEN...ELSE
文とループ)
例外処理文
他のOracleのストアド・プロシージャとストアド・ファンクションへのコール
レコード、表およびカーソルのFOR
ループなどの特別なPL/SQL機能
カーソル変数
Oracle Objects for OLE(OO4O)は、PL/SQLのストアド・プロシージャとの緊密な統合を提供します。OO4Oは、PL/SQLストアド・プロシージャ、PL/SQL表およびPL/SQLカーソルなどをサポートします。PL/SQLバインド変数は、OraParameter
のAdd
メソッドを介してサポートされます。
ストアド・プロシージャ・ブロックは、CreateSQL
メソッドまたはExecuteSQL
メソッドのいずれかを使用して実行されます。
Oracle Objects for OLEは、ストアド・プロシージャまたはPL/SQLの無名ブロックで作成されたカーソルを、READONLY
ダイナセット・オブジェクトとして戻すことができます。このためには、カーソル変数をORATYPE_CURSOR
型のOraParameter
オブジェクトとして割り当てる必要があります。
ストアド・プロシージャを実行した後、このOraParameter
オブジェクトのValue
プロパティは、読取り専用のダイナセット・オブジェクトを戻します。
このダイナセット・オブジェクトは、他のダイナセット・オブジェクトと同様に処理できます。
OO4Oでは、次の例に示すように、OraDatabase
オブジェクトのExecuteSQL
またはCreateSQL
メソッドを使用して、PL/SQLブロックを実行できます。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
'Add EMPNO as an Input parameter and set its initial value.
EmpDb.Parameters.Add "EMPNO", 7369, ORAPARM_INPUT
EmpDb.Parameters("EMPNO").ServerType = ORATYPE_NUMBER
'Add ENAME as an Output parameter and set its initial value.
EmpDb.Parameters.Add "ENAME", 0, ORAPARM_OUTPUT
EmpDb.Parameters("ENAME").ServerType = ORATYPE_VARCHAR2
'Add SAL as an Output parameter
EmpDb.Parameters.Add "SAL", 0, ORAPARM_OUTPUT
EmpDb.Parameters("SAL").ServerType = ORATYPE_NUMBER
'Add COMMISSION as an Output parameter and set its initial value.
EmpDb.Parameters.Add "COMMISSION", 0, ORAPARM_OUTPUT
EmpDb.Parameters("COMMISSION").ServerType = ORATYPE_NUMBER
EmpDb.ExecuteSQL ("BEGIN SELECT ename, sal, comm INTO :ENAME, :SAL," & _
":COMMISSION FROM emp WHERE empno = :EMPNO; END;")
'display the values of Ename, Sal, Commission parameters
MsgBox "Name: " & EmpDb.Parameters("ENAME").Value
MsgBox "Salary " & EmpDb.Parameters("SAL").Value
MsgBox "Commission: " & EmpDb.Parameters("COMMISSION").Value
次の例では、OO4OのCreateSQL
メソッドを使用してストアド・プロシージャをコールするPL/SQLブロックを実行します。このプロシージャは、入力情報として部門番号を使用し、部門の名前と所在地を戻します。
この例は、従業員データベースにストアド・プロシージャを作成するために使用されます。
CREATE OR REPLACE PACKAGE Department as PROCEDURE GetDeptName (inDeptNo IN NUMBER, outDeptName OUT VARCHAR2, outDeptLoc OUT VARCHAR2); END Department; / CREATE OR REPLACE PACKAGE BODY Department as PROCEDURE GetDeptName(inDeptNo IN NUMBER, outDeptName OUT VARCHAR2, outDeptLoc OUT VARCHAR2) is BEGIN SELECT dname, loc into outDeptName, outDeptLoc from DEPT WHERE deptno = inDeptNo; END; END Department; /
次の例では、前述のプロシージャを実行して、deptno
が10
である部門の名前と所在地を取得します。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
empDb.Parameters.Add "DEPTNO", 10, ORAPARM_INPUT
empDb.Parameters("DEPTNO").ServerType = ORATYPE_NUMBER
empDb.Parameters.Add "DNAME", 0, ORAPARM_OUTPUT
empDb.Parameters("DNAME").ServerType = ORATYPE_VARCHAR2
empDb.Parameters.Add "DLOC", 0, ORAPARM_OUTPUT
empDb.Parameters("DLOC").ServerType = ORATYPE_VARCHAR2
Set PlSqlStmt = empDb.CreateSQL("Begin Department.GetDeptname" & _
"(:DEPTNO, :DNAME, :DLOC); end;", 0&)
'Display Department name and location
MsgBox empDb.Parameters("DNAME").Value & empDb.Parameters("DLOC").Value
PL/SQLカーソル変数は主に、PL/SQLブロックからの1つ以上の問合せ結果セット、ストアド・プロシージャおよびファンクションにアクセスするために使用されます。OO4OのOraParameter
オブジェクトは、PL/SQLカーソル変数を保持するために使用できます。
カーソル変数を表すOraParameter
オブジェクトは、ORATYPE_CURSOR
型である必要があり、出力変数としてのみ定義できます。PL/SQLブロックを実行した後、OraParameter
オブジェクトのValue
プロパティには、読取り専用のOraDynaset
オブジェクトが含まれます。このOraDynaset
オブジェクトを使用すると、戻された行をスクロールできます。
場合によっては、PL/SQLプロシージャの実行には、ExecuteSQL
メソッドよりもCreateSQL
メソッドの使用が適切です。OraSQLStmt
オブジェクトのRefresh
メソッドを実行すると、PL/SQLカーソルの状態が変化する場合があります。CreateSQL
メソッドを使用した場合、変化したカーソルは既存のダイナセット・オブジェクトに自動的に関連付けられ、新しいダイナセット・オブジェクトは作成されません。
ダイナセット・オブジェクトのSQLプロパティは設定できません。設定しようとするとエラーになります。
注意: テーブル・パラメータとしてカーソルを含んだPL/SQLストアド・プロシージャはサポートされていません。 |
パラメータ・オブジェクトのRemove
メソッドをコールしてください。このメソッドは、ダイナセット・オブジェクトおよびローカル一時キャッシュ・ファイルの廃棄に便利です。
次の例では、emp
とdept
表のカーソルを取得するストアド・プロシージャとこのプロシージャを実行する小規模なアプリケーションを示します。
ストアド・プロシージャ
CREATE PACKAGE EmpAndDept AS cursor emp is select * from emp; cursor dept is select * from dept; TYPE EmpCurTyp IS REF CURSOR RETURN emp%ROWTYPE; TYPE DeptCurTyp IS REF CURSOR RETURN dept%ROWTYPE; PROCEDURE GetEmpAndDeptData (emp_cv OUT EmpCurTyp, dept_cv OUT DeptCurTyp); END EmpAndDept;/ CREATE PACKAGE BODY EmpAndDept AS PROCEDURE GetEmpAndDeptData (emp_cv OUT EmpCurTyp, dept_cv OUT DeptCurTyp) IS BEGIN OPEN emp_cv FOR SELECT * FROM emp; OPEN dept_cv FOR SELECT * FROM dept; END GetEmpAndDeptData; END EmpAndDept; /
アプリケーション
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
empDb.Parameters.Add "EMPCUR", 0, ORAPARM_OUTPUT
empDb.Parameters("EMPCUR").serverType = ORATYPE_CURSOR
empDb.Parameters.Add "DEPTCUR", 0, ORAPARM_OUTPUT
empDb.Parameters("DEPTCUR").serverType = ORATYPE_CURSOR
Set PlSqlStmt = empDb.CreateSql("Begin EmpAndDept.GetEmpAndDeptData (:EMPCUR," & _
":DEPTCUR); end;", 0)
Set EmpDynaset = empDb.Parameters("EmpCur").Value
Set DeptDynaset = empDb.Parameters("DeptCur").Value
MsgBox EmpDynaset.Fields("ENAME").Value
MsgBox DeptDynaset.Fields("DNAME").Value
PL/SQL表は、主としてPL/SQLデータの配列にアクセスするために使用されます。OO4OのOraParamArray
オブジェクトは、PL/SQLカーソル変数を保持するために使用できます。
表の変数を表すOraParamArray
オブジェクトは、AddTable
メソッドを使用して最初に作成する必要があります。表の値は、OraParamArray
オブジェクトのGet_Value
とPut_Value
メソッドを使用して、アクセスまたは設定します。
PL/SQLプロシージャのGetEmpNamesInArray
は、EMPNO
の配列に対するENAME
値の配列を戻します。
CREATE PACKAGE EmpNames AS type NUMARRAY is table of NUMBER index by BINARY_INTEGER; --Define EMPNOS array type VCHAR2ARRAY is table of VARCHAR2(10) index by BINARY_INTEGER; --Define ENAMES array PROCEDURE GetEmpNamesInArray (ArraySize IN INTEGER, inEmpnos IN NUMARRAY, outEmpNames OUT VCHAR2ARRAY); END EmpNames; / CREATE PACKAGE BODY EmpNames AS PROCEDURE GetEmpNamesInArray (ArraySize IN INTEGER, inEmpnos IN NUMARRAY, outEmpNames OUT VCHAR2ARRAY) is BEGIN FOR I in 1..ArraySize loop SELECT ENAME into outEmpNames(I) from EMP WHERE EMPNO = inEmpNos(I); END LOOP; END; END EmpNames; /
次の例では、前述のプロシージャを実行してename
表を取得します。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set Empdb = OO4OSession.OpenDatabase("Exampledb", "scott/tiger", 0)
Empdb.Parameters.Add "ArraySize", 3, ORAPARM_INPUT
Empdb.Parameters.AddTable "EMPNOS", ORAPARM_INPUT, ORATYPE_NUMBER, 3, 22
Empdb.Parameters.AddTable "ENAMES", ORAPARM_OUTPUT, ORATYPE_VARCHAR2, 3, 10
Set EmpnoArray = Empdb.Parameters("EMPNOS")
Set EnameArray = Empdb.Parameters("ENAMES")
'Initialize the newly created input parameter table EMPNOS
EmpnoArray(0) = 7698
EmpnoArray(1) = 7782
EmpnoArray(2) = 7654
Empdb.ExecuteSQL ("Begin EmpNames.GetEmpNamesInArray(:ArraySize," & _
":EMPNOS, :ENAMES); End;")
MsgBox EnameArray(0)
MsgBox EnameArray(1)
MsgBox EnameArray(2)
データ定義言語(DDL)文は、データベースのスキーマ・オブジェクトを管理します。DDL文は、新しい表の作成、古い表の削除、および他のスキーマ・オブジェクトの確立を実行します。また、スキーマ・オブジェクトへのアクセスも制御します。次に、例を示します。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
EmpDb.ExecuteSQL("create table employees (name VARCHAR2(20)," & _
"ssn VARCHAR2(12), empno NUMBER(6), mgr NUMBER(6), salary NUMBER(6)")
EmpDb.ExecuteSQL("GRANT UPDATE, INSERT, DELETE ON employees TO donna")
EmpDb.ExecuteSQL("REVOKE UPDATE ON employees FROM jamie")
DDL文を使用すると、Oracle Databaseのオブジェクトも処理できます。次に例を示します。
Set OO4OSession = CreateObject("OracleInProcServer.XOraSession")
Set EmpDb = OO4OSession.OpenDatabase("ExampleDb", "scott/tiger", 0)
EmpDb.ExecuteSQL("create type person_t as object (name VARCHAR2(30)," & _
"ssn VARCHAR2(12),address VARCHAR2(50))")
EmpDb.ExecuteSQL("create table person_tab OF person_t")
トランザクションは論理的な作業単位で、1人のユーザーが実行する1つ以上のSQL文で構成されています。一般的な例は、ある銀行口座から別の銀行口座への送金です。これには2つの操作が発生します。
口座から金額が引き落とされます。
別の口座にその金額が入金されます。
この2つの操作は一緒に実行する必要があります。(ネットワークの接続故障などで)片方の操作が実行され、他方の操作が実行されないと、銀行帳簿は正しく貸借一致しません。
通常、ダイナセットでUpdateメソッドを実行すると、変更内容はデータベースにただちにコミットされます。各操作は個別のトランザクションとして扱われます。OraSession
オブジェクトのBeginTrans
、CommitTrans
およびRollback
トランザクション制御メソッドを使用すると、複数の操作を1つの大きいトランザクションにグループ化できます。
BeginTrans
メソッドは、操作グループの開始をセッションに通知します。CommitTrans
メソッドは、操作グループ全体を確定します。Rollback
メソッドは、グループ全体を取り消します。CommitTrans
およびRollback
メソッドがトランザクションを終了すると、プログラムは1つの操作につき1つのトランザクションという通常の操作に戻ります。経験のあるOracle Databaseユーザーは、次に示すOracle Objects for OLEの操作とOracle Databaseのツール製品との違いに注意してください。
SQL*PlusなどのOracle Databaseのツール製品は、そのツールの起動時にBeginTrans
メソッドがコールされたものとして実行されます。これは、更新はただちにはコミットされず、コミットまたはロールバックの実行まで保留されることを意味します。
SQL*Plusは、コミットまたはロールバックが実行されるたびに、新しいトランザクションを開始します。
UPDATE
またはDELETE
文に失敗した場合、SQL*Plusは行をロックしません。ただし、OO4Oの場合、グローバル・トランザクション内のダイナセットの指定行でUPDATE
またはDELETE
メソッドに失敗した場合(BeginTrans
メソッドを発行した場合など)は、これらの指定行がロックされたままになることに注意してください。このロックは、CommitTrans
またはRollback
メソッドをコールするまで解除されません。
複数のデータベースに接続してトランザクション・メソッドを使用する場合、Oracle Objects for OLEでは各データベースが個別にコミットされることに注意してください。これは、Oracle Databaseが提供する2フェーズ・コミットとは異なります。データベース間のデータ整合をアプリケーションで保証する必要がある場合は、1つのデータベースに接続した状態で、Oracle Databaseのリンク機能を使用して他のデータベースにアクセスしてください。この方法によって、Oracle Databaseの2フェーズ・コミットの利点を利用できます。2フェーズ・コミット、データベース・リンクおよび分散トランザクションの詳細は、Oracle Databaseのドキュメントを参照してください。
トランザクションは、SQL言語のデータ操作言語(DML)部分(INSERT
、UPDATE
およびDELETE
文など)にのみ適用されます。トランザクションは、SQL言語のデータ制御言語(DCL)部分やデータ定義言語(DDL)部分(CREATE
、DROP
、ALTER
文など)には適用されません。DCLおよびDDLコマンドは常にコミットを強制し、前に処理したすべてを順にコミットします。
Oracle Objects for OLE(OO4O)で開始したOracleデータベース・トランザクションは、次のすべての条件が満たされた場合、Microsoft Transaction Server(MTS)のMicrosoft Distributed Transaction Coordinator(DTC)によって調整されたグローバル・トランザクションに自動的に関与します。
OraSession
のOpenDatabase
メソッドがORADB_ENLIST_IN_MTS
オプションを使用していること
OO4OがMTSのグローバル・トランザクションのコンテキスト内で実行されていることが確認されていること
Oracle Services for Microsoft Transaction Serverがインストールされ、実行中であること
OO4Oオートメーションでは、非同期処理を使用してコマンドを実行できます。これによって、SQL文とPL/SQLブロックを非ブロック・モードで実行できます。非ブロック・モードは、CreateSQL
メソッドのオプションです。
非ブロック・モードでは、実行が完了していない場合でも、制御がアプリケーションにただちに戻されます。このため、アプリケーションでは最後の実行結果に依存しない他のタスクを実行できます。
非ブロック・モードを有効にするには、OraSQLStmt
オブジェクトの作成時に、CreateSQL
メソッドにORASQL_NONBLK
オプションを渡します。このモードを指定しないと、OraSQLStmt
オブジェクトはブロック・モードで実行されます(デフォルト動作)。
'Create the statement in NON-BLOCKING mode OraSQL = Oradb.CreateSQL("delete from emp",ORASQL_NONBLK)
非ブロック・モードで作成されたOraSQLStmt
オブジェクトは、そのオブジェクトが有効な間、非ブロック・モードで実行されます。
この項の内容は次のとおりです。
非同期で実行されているOraSQLStmt
オブジェクトの状態を判断するには、アプリケーションでNonBlockingState
プロパティのポーリングを行う必要があります。実行が保留されている場合、NonBlockingState
プロパティはORASQL_STILL_EXECUTING
を戻し、実行が正常に完了した場合はORASQL_SUCCESS
を戻します。
エラーは、例外として発生します。
正常に完了したときに、出力パラメータがあれば、その内容がバインド・パラメータ・バッファに配置されます。アプリケーションは、ブロックの場合と同様にパラメータにアクセスできます。
次の例では、NonBlockingState
プロパティの使用方法を示します。
Dim OraDatabase as OraDatabase
Dim OraStmt as OraSQLStmt
Dim stat as long
Dim OraSess as OraSession
Set OraSess = CreateObject("OracleInProcServer.XOraSession")
Set OraDatabase =OraSess.OpenDatabase("ExampleDb", "scott/tiger", 0)
'execute the select statement with NONBLOCKING mode on
set OraStmt = OraDatabase.CreateSQL ("update emp set sal = sal + 1000", _
ORASQL_NONBLK)
'Check if the call has completed
stat = OraStmt.NonBlockingState
while stat = ORASQL_STILL_EXECUTING
MsgBox "Asynchronous Operation under progress"
stat = OraStmt.NonBlockingState
wend
MsgBox "Asynchronous Operation completed successfully"
実行中の非ブロック操作は、非同期コールを実行しているOraSQLStmt
オブジェクトに対してCancel
メソッドをコールすることによって取り消すことができます。
Dim OraDatabase as OraDatabase
Dim OraStmt as OraSQLStmt
Dim stat as long
Dim OraSess as OraSession
Set OraSess = CreateObject("OracleInProcServer.XOraSession")
Set OraDatabase =OraSess.OpenDatabase("ExampleDb", "scott/tiger", 0)
'execute the select statement with NONBLOCKING mode on
set OraStmt = OraDatabase.CreateSQL ("update emp set sal = sal + 1000", _
ORASQL_NONBLK)
'Check if the call has completed
stat = OraStmt.NonBlockingState
if stat = ORASQL_STILL_EXECUTING
MsgBox "Cancelling the asynchronous operation that is underway"
OraStmt.Cancel
End if
非同期モードでは、複数の問合せを実行できます。この例では、最初の接続が非ブロック・コールを実行している間に、2番目の接続がSQL文をブロック・モードで実行します。
Dim OraSess as OraSession
Dim OraServ as OraServer
Dim OraDb1 as OraDatabase
Dim OraDb2 as OraDatabase
Dim OraStmtnonblk as OraSQLStmt
Dim OraStmtblk as OraSQLStmt
Dim stat as long
set OraSess = CreateObject("OracleInProcServer.XOraSession")
set OraDb1 = OraSess.OpenDatabase("exampledb","scott/tiger",0&)
Set OraServ = CreateObject("OracleInProcServer.XOraServer")
set OraDb2 = OraServ.OpenDatabase("Exampledb","scott/tiger",0&)
'execute the select statement with NONBLOCKING mode on
set OraStmtnonblk = OraDb1.CreateSQL ("update emp set sal = sal + 1000", _
ORASQL_NONBLK)
'Check if the call has completed
stat = OraStmt.NonBlockingState
while stat = ORASQL_STILL_EXECUTING
MsgBox "Asynchronous Operation under progress"
stat = OraStmt.NonBlockingState
wend
MsgBox "Asynchronous Operation completed successfully"
'execute on the second connection in BLOCKING mode
set OraStmtblk = OraDb2.CreateSQL ("update emp set sal = sal + 500",0&)
非ブロック・モードには次のような制約があります。
OraSQLStmt
オブジェクトで非ブロック操作を実行している場合、そのオブジェクトのプロパティまたは属性は変更できません。これは、進行中の実行に影響を与える可能性があるためです。
すでにインスタンス化されている他のオブジェクトが接続上に存在する場合は、非ブロック・モードでOraSQLStmt
オブジェクトを作成することはできません。つまり、非ブロック・モードでOraSQLStmt
オブジェクトを作成して実行できるのは、OraDynaset
やOraAQ
などの他のオブジェクトが、同じデータベース・セッションで現在アクティブでない場合のみです。OraParameter
とOraObject
オブジェクトは例外です。これらのオブジェクトは非ブロック化の実行に必要な場合があるため、許可されています。