このクイック・ツアーは、Visual Basic用Oracle Objects for OLEを開発者が使用開始できるように作成されています。サンプル・アプリケーションである従業員データベース・アプリケーションでは、データ間のナビゲートやレコードの追加、修正、問合せなどの、データベースの基本操作をプログラミングする方法を示します。上級者向けの項では、パラメータ配列およびSQL文オブジェクトを使用したバッチ挿入の実行方法を示します。このクィック・ツアーおよびサンプル・アプリケーションでは、Scott/Tigerスキーマがインストールされていることを前提としています。
このサンプル・アプリケーションの全コードは、ORACLE_BASE\\ORACLE_HOME\OO4O\VB\SAMPLES\QT\ディレクトリに提供されています。
このクイック・ツアーの内容は次のとおりです。
この項では、従業員データベース・アプリケーション、およびそのアプリケーションを使用するためにユーザーが使用する2つのVisual Basicフォームの概要を示します。
従業員データベース・アプリケーションでは、ユーザーは次の操作を実行できます。
データの参照
レコードの追加
レコードの更新
データベースの問合せ
バッチ操作でのレコードの追加
これらの機能を提供するために、例では次のフォームを使用しています。
従業員フォームには、データベースEMP表のフィールドが表示され、そこには、ユーザーがレコードを参照、追加、更新および問合せ可能な機能ボタンがあります。
図6-1に、従業員フォームを示します。
|
関連項目:
|
サーバー・データを操作する前に、この項で説明する4つの手順をアプリケーションで完了しておく必要があります。この例のサンプル・コードは、「Form_Loadプロシージャの完全サンプル・コード」に示されています。
Oracleインプロセス・オートメーション・サーバーを開始します。
Oracleインプロセス・サーバー(OIP)では、Visual BasicアプリケーションとOracle Database間のインタフェースが提供されています。Oracleインプロセス・サーバーを開始するには、次に示すように、Visual BasicのCreateObject()ファンクションを使用してOraSessionオブジェクトを作成する必要があります。
Set OraSession = CreateObject("OracleInProcServer.XOraSession")
OraSessionオブジェクトを作成する場合、CreateObject()ファンクションに指定される引数は、常にOracleInProcServer.XOraSessionである必要があります。引数の左側にはシステムに登録されているアプリケーション名を指定し、この場合はOracleInProcServerです。右側には作成するオブジェクトのタイプを指定し、この場合はXOraSessionオブジェクトです。このコマンドを実行すると、Oracleインプロセス・サーバーが開始されます。
Oracleデータベースへの接続
OIPサーバーの実行後は、ローカルまたはリモートのOracleデータベースに接続できます。そのためには、次に示すように、OraDatabaseオブジェクトを作成する必要があります。
Set OraDatabase = OraSession.OpenDatabase("Exampledb", "scott/tiger", _
ORADB_DEFAULT)
OraSession.OpenDatabase()メソッドでは、OraDatabaseオブジェクトが作成されます。メソッド・コールでは、データベース名、接続文字列、およびデータベース・モードを表すビット・フラグを指定する必要があります。定数ORADB_DEFAULTは、デフォルトのデータベース・モードを表します。Visual Basicがこの行を実行すると、指定されたデータベースへの接続が作成されます。
データを操作するためにグローバル・オブジェクトOraDynasetを作成します。
Oracle Objects for OLEでは、ユーザーからのデータの参照および更新用に、ダイナセットと呼ばれるオブジェクトを使用します。
従業員アプリケーションには、プログラムの残り部分からもアクセス可能な、グローバル・ダイナセットが必要です。OraDatabase.CreateDynaset()メソッドでは、有効なSQL SELECT文を指定してダイナセットを作成します。次に示す例では、SQL文によってemp表からすべての行が選択され、作成されたダイナセットがグローバル変数EmpDynasetに割り当てられます。
Set EmpDynaset = OraDatabase.CreateDynaset("select * from emp", _
ORADYN_DEFAULT)
CreateDynaset()メソッドでは、SQL SELECT文の結果へのポインタが戻されます。
ORADYN_DEFAULTパラメータ値は、ダイナセットのデフォルト状態を指定します。Oracle Objects for OLEがデフォルト状態の場合、AddNewメソッドを使用してレコードを追加する際、未指定のフィールドはNULLに設定されます。emp表では列デフォルトが定義されないため、この動作が役立ちます。他のオプションを指定して、レコード追加時にサーバー列デフォルトを設定することも可能です。
ダイナセット・データを使用して従業員フォームをリフレッシュします。
従業員フォームでは、データベース・レコードが1回に1行ずつ表示されます。別の行へのナビゲートなどによる現在の行の変更は、画面上に反映される必要があります。EmpRefresh()サブルーチンは、ダイナセットの現在の行を使用してフィールドを更新します。フィールド値がNULLの場合は、空の文字列が表示されます。
次に、EmpRefresh()サブルーチンの例を示します。
Private Sub EmpRefresh()
'check if the current dynaset row is valid
If EmpDynaset.BOF <> True And EmpDynaset.EOF <> True Then
txtEmpno = EmpDynaset.Fields("empno").Value
' we can't display nulls, so display "" for NULL fields
If Not IsNull(EmpDynaset.Fields("ename").Value) Then
txtEname = EmpDynaset.Fields("ename").Value
Else
txtEname = ""
End If
If Not IsNull(EmpDynaset.Fields("job").Value) Then
txtJob = EmpDynaset.Fields("job").Value
Else
txtJob = ""
End If
'check if mgr=nul
If Not IsNull(EmpDynaset.Fields("mgr").Value) Then
txtMgr = EmpDynaset.Fields("mgr").Value
Else
txtMgr = ""
End If
If Not IsNull(EmpDynaset.Fields("hiredate").Value) Then
txtHireDate = EmpDynaset.Fields("hiredate").Value
Else
txtHireDate = ""
End If
If Not IsNull(EmpDynaset.Fields("hiredate").Value) Then
txtSal = EmpDynaset.Fields("sal").Value
Else
txtSal = ""
End If
'check if comm=nul
If Not IsNull(EmpDynaset.Fields("comm").Value) Then
txtComm = EmpDynaset.Fields("comm").Value
Else
txtComm = ""
End If
txtDeptno = EmpDynaset.Fields("deptno").Value
'if the current dynaset row is invalid, display nothing
Else
txtEmpno = ""
txtEname = ""
txtJob = ""
txtMgr = ""
txtHireDate = ""
txtSal = ""
txtComm = ""
txtDeptno = ""
End If
End Sub
前の項で説明した従業員アプリケーションでは、Form_Load()プロシージャにより、OIPサーバーの作成、データベースへの接続、およびグローバル・ダイナセットの作成を行い、EmpRefreshファンクションをコールして従業員フォームでフィールド値を表示しています。次に、Form_Load()プロシージャの例を示します。
Private Sub Form_Load()
'OraSession and OraDatabase are global
Set OraSession = CreateObject("OracleInProcServer.XOraSession")
Set OraDatabase = OraSession.OpenDatabase("Exampledb", "scott/tiger", 0&)
Set EmpDynaset = OraDatabase.CreateDynaset("select * from emp", 0&)
Call EmpRefresh
End Sub
次の変数は、EMP_QT.BASでは、グローバル変数として定義する必要があります。
Global OraSession As Object Global OraDatabase As Object Global EmpDynaset As Object
この項では、従業員フォームの詳細、および使用されるファンクションについて説明します。
従業員フォームには、データベースのEMP表のフィールドが表示され、そこには、ユーザーによるレコードの参照、追加、更新、問合せを可能にする機能ボタンがあります。
各フィールドは、データベースのEMP表の各列に対応しています。「Employee」フィールド(ENAME)は索引付けされた列であり、各レコードに対して必要です。EMP表のフィールドのデータ型とサイズは、次のように定義されています。
Name Null? Type ----------------------- ---------- -------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NOT NULL NUMBER(2)
「Employee Number」(EMPNO)と「Department」(DEPTNO)の列はNOT NULLであるため、レコード追加時に常に値が必要です。各フィールドの長さは、それぞれのTextBoxのMaxLengthプロパティを適切な数字に設定することで設定されます。
図6-3に、従業員フォームを示します。
実際のForm_Loadプロシージャの初期化コードは、「Form_Loadプロシージャの完全サンプル・コード」に示されています。
従業員フォームは、Form_Load()プロシージャにより初期化され、次の機能を含みます。
一般的に、データベース・アプリケーションでは、ユーザーがデータベースのデータを表示できる必要があります。従業員フォームには4つのボタンがあり、ユーザーはデータをスクロールできます。表6-1に、各ボタンとその機能、各ボタンのアクションを有効にするダイナセットの移動メソッド、および詳細情報の参照先を示します。
表6-1 ナビゲーショナル・ボタンおよびダイナセットの移動メソッド
| ボタン | アクション | メソッド | 参照先 |
|---|---|---|---|
|
|
最初のレコードへ移動 |
|
|
|
|
前のレコードへ移動 |
|
|
|
|
次のレコードへ移動 |
|
|
|
|
最後のレコードへ移動 |
|
|
従業員データベースのレコード間のナビゲーションを可能にするには、最初に、すべてのレコード(行)を選択するグローバル・ダイナセットを作成する必要があります。その後、ダイナセットの移動メソッドを使用して、ナビゲーショナル・ボタンをプログラミングします。
ダイナセットの最初の行への移動を可能にするには、MoveFirstメソッドを使用します。その後、従業員フォームのデータをリフレッシュするEmpRefresh()ルーチンをコールします。
次のサンプル・コードは、サンプル従業員レコードの最初の行へのクリック・イベントのプロシージャを示しています。
Private Sub cmdFirst_Click() EmpDynaset.MoveFirst Call EmpRefresh End Sub
最後の行への移動には、MoveLastメソッドを使用します。その後、従業員フォームのデータをリフレッシュするEmpRefresh()ルーチンをコールします。
次のサンプル・コードは、サンプル従業員レコードの最後の行へのクリック・イベントのプロシージャを示しています。
Private Sub cmdLast_Click() EmpDynaset.MoveLast Call EmpRefresh End Sub
ダイナセットでは、任意の行へナビゲーションが可能です。ユーザーがダイナセットの中間(つまり現在の行が最初の行ではない)を参照している場合、MovePreviousメソッドで前の行へナビゲーションできます。
ただし、ユーザーが最初の行を参照している場合(現在の行が最初の行の場合)にMovePreviousメソッドを実行すると、BOF(ファイルの先頭)条件がTRUEに設定され、現在の行が無効になります。この場合、MoveFirstメソッドを使用して、現在の行を最初の行にリセットする必要があります。
次のサンプル・コードは、前の行へのボタン・クリック・イベントのプロシージャを示しています。
Private Sub cmdPrevious_Click() If EmpDynaset.BOF <> True Then EmpDynaset.DbMovePrevious If EmpDynaset.BOF = True Then MsgBox WarnFirstEmp$ EmpDynaset.DbMoveFirst End If End If
ユーザーがダイナセットの中間(つまり現在の行が最後の行ではない)を参照している場合、MoveNextメソッドで次の行へナビゲーションできます。
ただし、ユーザーが最後の行を参照している場合(現在の行が最後の行の場合)にMoveNextメソッドを実行すると、EOF(ファイルの最後)条件がTRUEに設定され、現在の行が無効になります。この場合、MoveLastメソッドを使用して、現在の行を最後の行にリセットする必要があります。
次のサンプル・コードは、次の行へのボタン・クリック・イベントのプロシージャを示しています。
Private Sub cmdNext_Click() If EmpDynaset.EOF <> True Then EmpDynaset.DbMoveNext If EmpDynaset.EOF = True Then MsgBox WarnLastEmp$ EmpDynaset.DbMoveLast End If End If
このサンプル・アプリケーションでは、ユーザーは次のボタンでデータベースに従業員レコードを追加できます。
Add
Commit
レコードを追加するには、ユーザーは、「Add」ボタンをクリックして、テキスト・ボックスに新規フィールドを入力した後、「Commit」ボタンをクリックしてデータベースにデータを保存します。
追加イベント・プロシージャでは、次の手順を実行する必要があります。
フォーム上のフィールドの消去。
「Add」ボタンの無効化。
「Commit」ボタンの有効化。
ユーザーによる新規フィールド値の入力。
次のサンプル・コードは、「Add」ボタンのための追加イベント・プロシージャを示しています。
Private Sub AddNew_Click()
'Blank out the fields
txtEmpno = ""
txtEname = ""
txtJob = ""
txtMgr = ""
txtHireDate = ""
txtSal = ""
txtComm = ""
txtDeptno = ""
'Disable the Add button and enable the commit button
AddNew.Enabled = False
Commit.Enabled = True
'Disable the navigation buttons
DisableNavButtons
'Set doadd to true for commit procedure
DoAdd = True
End Sub
AddNew_Click()メソッドが存在する場合、ユーザーがフィールド値を入力している従業員フォームへ、コントロールが戻ります。
追加をコミットするには、AddNewメソッドを使用してダイナセットを追加モードにします。その後、新規データをダイナセットのフィールドに割り当て、Updateメソッドを使用してデータベースを更新します。プログラムを堅牢にするために、このソフトウェアでは、一部のフィールドがデータベースへの追加前に検証されます。
Commit_Click()イベント・プロシージャでは、レコードを追加するために、次の処理を実行する必要があります。
「Employee Number」フィールドと「Department」フィールドがnullでないことの確認。
新規の「Employee Number」が重複入力ではないことの確認。
手順1および手順2は、Commit_Click()の後に記述するDoValidationChecks()ファンクションにより実行されます。
AddNewメソッドによるダイナセットの追加モードへの設定。
Fields().Valueプロパティを使用した、ダイナセット・フィールドへの入力データの割当て。この手順は、UpdateDynasetFieldsファンクションにより実行されます。
Updateメソッドを使用した、新規レコードでのデータベースの更新。
「Commit」ボタンの無効化。
「Add」ボタンの有効化。
Commitファンクションのコードは、次のルーチンに分かれます。
次に、レコードを追加する典型的なCommit_Click()イベント・プロシージャを示します。
Private Sub Commit_Click()
On Error GoTo err_commit
ErrMsg = ""
'Do validation checks on entered data
If DoValidationChecks Then 'If validation checks have passed
'Add the new record to dynaset
EmpDynaset.AddNew
'Update the dynaset fields and then update database if there is no error.
If UpdateDynasetFields Then
'Update the database
EmpDynaset.Update
Commit.Enabled = False
AddNew.Enabled = True
Exit Sub
err_commit:
If ErrMsg <> "" Then
MsgBox ErrMsg
Else
MsgBox Error$
End If
End Sub
ステップ2で推奨するように重複入力を確認するには、入力された「Employee Number」フィールドに一致する行をカウントするSQL文を使用し、NOCACHEオプションを指定してローカル・ダイナセットを作成する必要があります。一致が見つかった(行カウントが0より大きい)場合、入力された従業員番号は重複入力で、エラーが表示されます。この場合、SQL SELECT文は数のみを戻すため、サーバーによる重複入力の検出よりも、キャッシュなしでダイナセットを作成する方が効率的なエラー・チェックとなります。
DoValidationChecks()は、入力データが有効な場合はTrueを戻します。そうでない場合は、Falseを戻します。
Function DoValidationChecks() As Boolean
Dim DupDyn As Object
Dim DupDynQry As String
On Error GoTo err_ValidationCheck
ErrMsg = ""
'Empno cannot be changed while in Update mode, so we can skip over validation
If DoAdd Then
If txtEmpno = "" Then
ErrMsg = "You must enter a value for Employee Number"
Error 1
End If
End If
If txtHireDate <> "" And Not IsDate(txtHireDate) Then
ErrMsg = "Enter date as dd-mmm-yy."
Error 2
End If
If txtDeptno = "" Then
ErrMsg = "You must enter a value for Department Number"
Error 3
End If
'If adding a record, check for Duplicate empno value by
'attempting to count rows with same value
'Build Query:
If DoAdd Then
DupDynQry = "select count(*) from emp where empno = " & txtEmpno
Set DupDyn = OraDatabase.CreateDynaset(DupDynQry, ORADYN_NOCACHE)
If DupDyn.Fields(0).Value <> 0 Then
ErrNum = DUPLICATE_KEY
ErrMsg = "Employee Number already exists."
Error ErrNum
End If
End If
'Succesful validation with no errors returns True
DoValidationChecks = True
Exit Function
err_ValidationCheck:
If ErrMsg <> "" Then
MsgBox ErrMsg
Else
MsgBox Error$
End If
'Validation returns false on failure
DoValidationChecks = False
End Function
コミット・イベント・プロシージャでは、ダイナセットをEditまたはAddNewモードにした後、このファンクションをコールします。UpdateDynasetFields()ファンクションは、テキスト・ボックスに入力された値をダイナセットのフィールドに設定します。ファンクションが正常に完了した場合はTRUEを戻し、エラーがある場合はFALSEを戻します。
Function UpdateDynasetFields() As Integer
'This function sets the dynaset field value to those entered in the text boxes.
'The function returns true on success, false on error.
ErrMsg = ""
On Error GoTo err_updatedynasetfields
EmpDynaset.Fields("empno").Value = txtEmpno
EmpDynaset.Fields("ename").Value = txtEname
EmpDynaset.Fields("job").Value = txtJob
EmpDynaset.Fields("mgr").Value = txtManager
EmpDynaset.Fields("hiredate").Value = txtHireDate
EmpDynaset.Fields("sal").Value = txtSal
EmpDynaset.Fields("comm").Value = txtComm
EmpDynaset.Fields("deptno").Value = txtDeptno
UpdateDynasetFields = True
Exit Function
err_updatedynasetfields:
If ErrMsg <> "" Then
MsgBox ErrMsg
Else
MsgBox Error$
End If
UpdateDynasetFields = False
ユーザーがデータベース内にある既存レコードを更新できるようにするには、従業員フォームに「Update」ボタンを含める必要があります。ユーザーは特定のレコードにナビゲートし、「Update」ボタンをクリックして変更を行った後、「Commit」ボタンをクリックします。
更新モードになっている間、アプリケーションでは次の制約が課されます。
ユーザーは、他のレコードへのナビゲートも他の機能の実行もできません。
従業員番号は主キーであるため、ユーザーによる変更はできません。
Updateファンクションをプログラミングするには、「Update」ボタンのイベント・プロシージャを記述し、コミット・プロシージャを、レコードの更新と追加の両方を処理できるように修正します。
「Update」ボタンのコーディングでは、主キーである「Employee Number」のテキスト・ボックスを無効化して、このフィールドがレコード更新時に変更されないようにします。また、ナビゲーションなどのその他の機能もレコード更新時に無効になるよう、他のボタンも無効化する必要があります。
DoUpdateブール式をTRUEに設定し、コミット・プロシージャが現行プロセスを追加ではなく更新の操作として認識できるようにします。
更新イベント・プロシージャでは、次の処理を実行する必要があります。
「Update」ボタンの無効化。
「Commit」ボタンの有効化。
更新操作時にナビゲーションなどの機能を無効化するための、他のボタンの無効化。
「Employee Number」テキスト・ボックスの無効化。
DoUpdateフラグのTrueへの設定。
ユーザーによる変更の入力。
次のサンプル・コードは、更新イベント・プロシージャを示しています。
Private Sub cmdUpdate_Click() 'Disable the Update button and enable the commit button cmdUpdate.Enabled = False Commit.Enabled = True 'Disable all other buttons DisableNavButtons txtEmpno.Enabled = False DoUpdate = True End Sub
更新および追加のイベント・プロシージャでは、追加または更新の操作中にナビゲーションおよびその他の機能を無効にするために、DisableNavButtons()サブルーチンをコールします。
Private Sub DisableNavButtons() 'disable all buttons while adding and updating cmdFirst.Enabled = False cmdPrevious.Enabled = False cmdNext.Enabled = False cmdLast.Enabled = False cmdFind.Enabled = False cmdUpdate.Enabled = False AddNew.Enabled = False End Sub
更新をコミットするプロシージャは追加をコミットするプロシージャと似ていますが、ダイナセットがEditメソッドにより編集モードに設定されて新規ダイナセット値が割り当てられる点が異なります。
追加と更新では、同じコミット・ボタンおよび同じコミット・イベント・プロシージャが使用されるため、追加と更新を区別するために2つのグローバル・フラグDoAddとDoUpdateが追加されます。「Add」および「Update」のクリック・イベント・プロシージャで、これらのフラグが設定されます。
追加と更新のコミット・イベント・プロシージャでは、次の処理を実行する必要があります。
DoValidationChecks()ファンクションを前述と同様に使用した、入力データの検証。
レコードの追加にはAddNew、更新にはEditの使用。
前述と同様にUpdateDynasetFields()を使用してFields().Valueプロパティを使用した、ダイナセット・フィールドへの入力データの割当て。
Updateを使用した、新規レコードでのデータベースの更新。
「Commit」ボタンの無効化。
「Add」ボタンおよび「Update」ボタンを含む、他のすべての機能ボタンの再有効化。
DoUpdateおよびDoAddフラグのFalseへの設定。
手順5から手順7に示すボタンおよびフラグの状態を変更するコードは、SetAfterCommitFlags()と呼ばれる新規サブルーチンで提供されます。これにより、最初にCommitおよびAddNewを有効化したコード行が置き換えられます。
このCommitファンクションのコードは、次のルーチンに分かれます。
DoValidationChecks( )ファンクション。元のCommitファンクションでも使用。
UpdateDynasetFields( )ファンクション。元のCommitファンクションでも使用。
SetAfterCommitFlags()サブルーチンの例。新規サブルーチン。
次の例は、Commit_Clickイベント・プロシージャを示しています。
Private Sub Commit_Click()
On Error GoTo err_commit
ErrMsg = ""
'Do validation checks on entered data
If DoValidationChecks Then 'If validation checks have passed
'If we are adding a record use AddNew
If DoAdd = True Then
EmpDynaset.AddNew
End If
'If we are updating a record use Edit
If DoUpdate = True Then
EmpDynaset.Edit
End If
'Update the dynaset fields and then update database if there is no error.
If UpdateDynasetFields Then
EmpDynaset.Update
End If
SetAfterCommitFlags
End If 'Endif for DoValidationChecks
Exit Sub
err_commit:
If ErrMsg <> "" Then
MsgBox ErrMsg
Else
MsgBox Error$
End If
End Sub
次の例は、SetAfterCommitFlag()サブルーチンを示しています。
SetAfterCommitFlags()サブルーチンは、コミット・イベント・プロシージャの最後にコールされます。SetAfterCommitFlags()サブルーチンは、無効化されたボタンおよびテキスト・ボックスを再度有効化し、DoUpdateおよびDoAddフラグをFalseに設定します。
Sub SetAfterCommitFlags() 'disable commit and re-enable add and update buttons Commit.Enabled = False AddNew.Enabled = True cmdUpdate.Enabled = True 'enable the other buttons cmdFirst.Enabled = True cmdPrevious.Enabled = True cmdNext.Enabled = True cmdLast.Enabled = True cmdFind.Enabled = True cmdUpdate.Enabled = True AddNew.Enabled = True DoUpdate = False DoAdd = False txtEmpno.Enabled = True End Sub
ユーザーは、特定のレコードにナビゲートして「Delete」ボタンをクリックすることで、レコードを削除できます。削除を確認するメッセージがアプリケーションから表示され、次にDeleteメソッドを使用してレコードが削除されます。次に、画面がリフレッシュされて、次のレコードまたは(ダイナセットの最後のレコードを削除した場合は)前のレコードが表示されます。
次の例は、削除クリック・イベント・プロシージャを示しています。
Private Sub cmdDelete_Click()
'prompt user
Response = MsgBox("Do you really want to Delete?", vbYesNo + vbExclamation)
If Response = vbYes Then
EmpDynaset.Delete
'attempt to move to next record
EmpDynaset.MoveNext
If EmpDynaset.EOF Then 'If deleted last record
EmpDynaset.MovePrevious
End If
Call EmpRefresh
End If
End Sub
従業員アプリケーションは、ユーザーがデータベース内で特定のレコードを検索できるように構成できます。デモ用に、従業員名のみを問い合せることができる「Find」ボタンが付いています。ユーザーはいつでも「Employee Name」フィールドに問合せを入力して、「Find」ボタンをクリックできます。その後、アプリケーションによって結果が表示されるか、名前が見つからなかった場合はメッセージが表示されます。
レコードの検索には、FindFirstメソッドを使用します。検索操作が正常に終了した場合、レコードが表示されます。検索に失敗した場合は、メッセージが表示されます。失敗するとダイナセットがBOF(ファイルの先頭)となるため、現在の行が最初の行に再設定され、現在の行は実質的に無効となります。
Find_Click()イベント・プロシージャでは、次の処理を実行する必要があります。
入力文字列と一致するENAME列を持つレコードを検索するためのfind句の構築。
FindFirstメソッドを使用した、検索の実行。
該当するレコードが見つかった場合のレコードの表示。見つからなかった場合のメッセージの表示および現在の行の最初の行への再設定。
次の例は、典型的な検索クリック・イベント・プロシージャを示しています。
Private Sub cmdFind_Click()
Dim FindClause As String
Dim SingleQuote As String
ErrMsg = ""
SingleQuote = "'"
On Error GoTo err_find
'build the find clause:
'Can make our query case insensitive by converting the names to upper case
'FindClause = "UPPER(ename) = " & SingleQuote & UCase(txtEname) & SingleQuote
FindClause = "ename = " & SingleQuote & txtEname & SingleQuote
EmpDynaset.DbFindFirst FindClause
If EmpDynaset.NoMatch Then
MsgBox "Could not find record matching Employee Name " & txtEname
EmpDynaset.DbMoveFirst
End If
Call EmpRefresh
Exit Sub
この項では、バッチ挿入フォームおよび使用されるファンクションについて説明します。
バッチ挿入フォームにより、ユーザーは、バッチ操作で行を挿入(1つのコマンドのみを使用して複数のレコードをデータベースに挿入)できます。この機能は、パラメータ配列およびSQL文を使用して実装されます。
表6-1に、一般的なバッチ挿入フォームを示します。
ユーザーは、従業員フォーム上の「Batch Insert」ボタンをクリックすることにより、バッチ挿入フォームにナビゲートします。バッチ挿入フォームには、入力済データを表示するグリッドと、ユーザーがレコードを入力するフィールド行が設けられています。例では、簡潔にするために、ユーザーには「Employee Number」、「Employee Name」および「Department Number」フィールドへの入力のみが許可されています。
ユーザーは、フィールドにレコードを入力し、「Add to Grid」ボタンをクリックします。プログラムにより、入力したレコードがグリッドに表示されます。バッチ全体をデータベースに挿入するには、ユーザーは「CommitGrid」ボタンをクリックします。
バッチ挿入フォームには、3つのプロシージャが使用されます。Form_Load()プロシージャは、列ヘッダーでグリッドを初期化します。CmdAddtoGrid_click()プロシージャは、入力データをフィールドからグリッドにコピーします。CommitGrid_Click()プロシージャには、バッチ挿入に使用するパラメータ配列およびSQL文が含まれます。
次に、これらのプロシージャを示します。
次の例は、バッチ挿入のForm_Load()プロシージャがグリッドの列ヘッダーを設定する方法を示しています。
Private Sub Form_Load()
Grid1.Enabled = True
CurrRow = 0 'Top row
ReadRow = 0
ReadCol = 0
'Set column headings
Grid1.Row = CurrRow
Grid1.Col = 0
Grid1.Text = "Employee Number"
Grid1.Col = 1
Grid1.Text = "Employee Name"
Grid1.Col = 2
Grid1.Text = "Department Number"
NoOfCols = 3
CurrRow = CurrRow + 1
End Sub
CmdAddtoGrid_Click()プロシージャは、フィールドに入力されたデータを、グリッドの次の空行にコピーします。グローバル変数CurrRowは、常に、グリッドの最初の空行を指します。
次の例は、CmdAddtoGrid_Click()を示しています。
Private Sub CmdAddtoGrid_Click() 'Update the grid 'Update Empno column Grid1.Row = CurrRow Grid1.Col = 0 Grid1.Text = txtEmpno 'Update Ename column Grid1.Row = CurrRow Grid1.Col = 1 Grid1.Text = txtEname 'Update Deptno column Grid1.Row = CurrRow Grid1.Col = 2 Grid1.Text = txtDeptno 'Increment CurrCol CurrRow = CurrRow + 1 NoOfRows = CurrRow - 1 End Sub
CommitGrid_Click()プロシージャは、グリッドのデータをデータベースに挿入します。これを行うために、このプロシージャでは、グリッドの各列に対応するEMP表の各列に対して、パラメータ配列オブジェクトを作成します。OraParameters.AddTable()メソッドでは、各パラメータ配列を定義します。たとえば、EMPNO_ARRというパラメータ配列では「Employee Number」列要素を保持する、などです。
パラメータ配列を定義した後、Put_Valueメソッドで各配列にグリッド列要素を移入します。
パラメータ配列要素をデータベースにコミットするために、このプロシージャでは、CreateSQL()メソッドを、パラメータ配列を含むSQL INSERT文とともに使用します。CreateSQL()メソッドでは、SQL文オブジェクトを作成するとともにSQL INSERT文も実行するため、この1つの文ですべての列要素(パラメータ配列要素)がEMP表に挿入されます。
パラメータ配列を含むSQL INSERT文の実行時にエラーが発生した場合も、SQL文オブジェクトは明示的なエラーとはならずに作成されます。このようなエラーを識別するには、CreateSQLメソッドの実行直後に、必ず、OraDatabase.LastServerErrおよびOraDatabase.LastServerErrTextプロパティをチェックします。
CreateSQLメソッドは、データベースを直接更新し、ダイナセットには影響しません。EmpDynaset.Refreshメソッドを使用してこのダイナセットをリフレッシュし、新しく挿入されたレコードがそれに反映されるようにする必要があります。
CommitGrid_Click()イベント・プロシージャでは、次の処理を実行する必要があります。
AddTableメソッドを使用した、各グリッド(データベース)列のパラメータ配列の定義。
ネステッド・ループ内でPut_Valueメソッド使用した、グリッド列要素のパラメータ配列へのコピー。
パラメータ配列要素をEMP表へ挿入するための、CreateSQLメソッドを使用したSQL文オブジェクトの作成。
SQL文実行エラーを識別するための、LastServerErrTextおよびLastServerErrプロパティの確認。
新規に挿入されたレコードを反映するための、Refreshメソッドを使用したグローバル・ダイナセットのリフレッシュ。
次の例は、典型的なcmdCommitGrid_Click()プロシージャを示しています。
Private Sub cmdCommitGrid_Click()
Dim OraSqlStmt As Object
Dim OraPArray(2) As Object
On Error GoTo err_CommitGrid
ErrMsg = ""
'Define parameter arrays, one for each column
OraDatabase.Parameters.AddTable "EMPNO_ARR", ORAPARM_INPUT, ORATYPE_NUMBER, _
NoOfRows
OraDatabase.Parameters.AddTable "ENAME_ARR", ORAPARM_INPUT, ORATYPE_VARCHAR2, _
NoOfRows, 10
OraDatabase.Parameters.AddTable "DEPTNO_ARR", ORAPARM_INPUT, ORATYPE_NUMBER, _
NoOfRows
If OraDatabase.LastServerErr <> 0 Or OraDatabase.LastServerErrText <> "" Then
Error 1
End If
'Initialize local array to hold parameter arrays
Set OraPArray(0) = OraDatabase.Parameters("EMPNO_ARR")
Set OraPArray(1) = OraDatabase.Parameters("ENAME_ARR")
Set OraPArray(2) = OraDatabase.Parameters("DEPTNO_ARR")
'Init the param array variables. Add loop to read thru grid ROWS
For ReadRow = 0 To (NoOfRows - 1)
Grid1.Row = ReadRow + 1
'Loop to read thru grid CELLS
For ReadCol = 0 To NoOfCols - 1
Grid1.Col = ReadCol
OraPArray(ReadCol).Put_Value Grid1.Text, ReadRow
Next ReadCol
Next ReadRow
'create a sqlstmt to insert array values into table
Set OraSqlStmt = OraDatabase.CreateSql("insert into emp(empno,ename,deptno)" & _
"values(:EMPNO_ARR,:ENAME_ARR,:DEPTNO_ARR)", 0&)
If OraDatabase.LastServerErr <> 0 Or OraDatabase.LastServerErrText <> "" Then
ErrMsg = OraDatabase.LastServerErrText
Error 1
End If
'Refresh the Dynaset
EmpDynaset.Refresh
OraDatabase.Parameters.Remove "EMPNO_ARR"
OraDatabase.Parameters.Remove "ENAME_ARR"
OraDatabase.Parameters.Remove "DEPTNO_ARR"
Exit Sub
err_CommitGrid:
If ErrMsg <> "" Then
MsgBox ErrMsg
Else
MsgBox Error$
End If
End Sub