レコードセット: AddNew、Edit、Delete の動作のしくみ (ODBC)
このトピックの内容は、MFC ODBC クラスに該当します。
このトピックでは、CRecordset
クラスのメンバー関数 AddNew
、Edit
、および Delete
がどのように機能するのかについて説明します。 取り上げるトピックは次のとおりです。
Note
このトピックの内容は、バルク行フェッチが実装されていない CRecordset
の派生オブジェクトを対象にしています。 バルク行フェッチを使用する場合は、「レコードセット: レコードの一括フェッチ (ODBC)」を参照してください。
補足として、「レコード フィールド エクスチェンジ: RFX の動作のしくみ」を参照してください。この記事では、更新操作における RFX の対応する役割について説明しています。
レコードの追加
レコードセットに新しいレコードを追加するには、レコードセットの AddNew メンバー関数を呼び出し、新しいレコードのフィールド データ メンバーの値を設定して、Update メンバー関数を呼び出してレコードをデータ ソースに書き込む必要があります。
AddNew
を呼び出す前提条件として、レコードセットは読み取り専用として開かないようにする必要があります。 メンバー関数 CanUpdate
および CanAppend
を使用すると、これらの条件を確認できます。
AddNew
を呼び出す場合:
操作が取り消された場合に内容を復元できるよう、編集バッファー内のレコードが格納されます。
後で変更を検出できるよう、フィールド データ メンバーにフラグが設定されます。 フィールド データ メンバーもクリーン (変更なし) とマークされ、Null に設定されます。
AddNew
を呼び出した後、編集バッファーは新しい空のレコードを表し、値を入力する準備ができた状態になります。 これを行うには、値を手動で割り当てて設定します。 フィールドの実際のデータ値を指定する代わりに、SetFieldNull
を呼び出して Null 値を指定することもできます。
変更をコミットするには、Update
を呼び出します。 新しいレコードに対して Update
を呼び出す場合:
ODBC ドライバーが
::SQLSetPos
ODBC API 関数をサポートしている場合、MFC はその関数を使用してデータ ソースにレコードを追加します。::SQLSetPos
を使用した場合、MFC では、SQL ステートメントを作成して処理する必要がないので、より効率的にレコードを追加できます。::SQLSetPos
を使用できない場合、MFC では次の手順が実行されます。変更が検出されなかった場合、
Update
は何も実行せず、0 を返します。変更がある場合は、
Update
は SQL INSERT ステートメントを構築します。 すべてのダーティ フィールド データ メンバーで表される列が、INSERT ステートメントにリストされます。 列を強制的に含めるには、SetFieldDirty メンバー関数を呼び出します。SetFieldDirty( &m_dataMember, TRUE );
Update
は新しいレコードをコミットします。INSERT ステートメントが実行され、トランザクションが進行中でない限り、レコードがデータ ソースのテーブル (およびレコードセット (スナップショットではない場合)) にコミットされます。格納されたレコードは編集バッファーへと復元されます。
AddNew
呼び出しの前に最新であったレコードは、INSERT ステートメントが正常に実行されたかどうかに関係なく、再び最新の状態になります。
ヒント
新しいレコードを完全に制御するには、次の方法を使用します。値を持つことになるすべてのフィールドの値を設定し、フィールドへのポインターとパラメーター TRUE (既定値) を指定して
SetFieldNull
を呼び出すことによって、Null のままにするフィールドを明示的に設定します。 フィールドがデータ ソースに書き込まれないようにしたい場合は、フィールドへのポインターとパラメーター FALSE を指定してSetFieldDirty
を呼び出し、フィールドの値を変更しないようにします。 フィールドを Null にできるかどうかを確認するには、IsFieldNullable
を呼び出します。ヒント
レコードセット データ メンバーが値をいつ変更したかを検出するために、MFC では、レコードセットに格納できる各データ型に適した PSEUDO_NULL 値が使用されます。 フィールドを明示的に PSEUDO_NULL 値に設定する必要がある場合で、フィールドが既に Null とマークされている場合は、
SetFieldNull
を呼び出し、最初のパラメーターでフィールドのアドレスを渡し、2 番目のパラメーターで FALSE を渡す必要があります。
追加されたレコードの表示
レコードセットに追加されたレコードはいつ表示されるのでしょうか? 追加されたレコードは、次の 2 つの要因によって、表示される場合と表示されない場合があります。
ドライバーが実行できる機能。
フレームワークで利用できる機能。
ODBC ドライバーが ::SQLSetPos
ODBC API 関数をサポートしている場合、MFC はその関数を使用してレコードを追加します。 ::SQLSetPos
を使用した場合、追加されたレコードは更新可能な MFC レコードセットに対して表示されます。 関数に対するサポートがない場合、追加されたレコードは表示されません。それらを表示するには、Requery
を呼び出す必要があります。 ::SQLSetPos
を使用した方が、より効率的でもあります。
既存のレコードの編集
レコードセット内の既存のレコードを編集するには、レコードにスクロールし、レコードセットの Edit メンバー関数を呼び出して、新しいレコードのフィールド データ メンバーの値を設定し、Update メンバー関数を呼び出して、変更されたレコードをデータ ソースに書き込む必要があります。
Edit
を呼び出す前提条件として、レコードセットは更新可能であり、1 つのレコード上である必要があります。 メンバー関数 CanUpdate
および IsDeleted
を使用すると、これらの条件を確認できます。 現在のレコードがまだ削除されていないことも条件となります。また、レコードセット内にレコードが存在する必要があります (IsBOF
と IsEOF
のどちらも 0 を返します)。
Edit
を呼び出すと、編集バッファー (現在のレコード) 内のレコードが格納されます。 格納されたレコードの値は、後でフィールドが変更されたかどうかを検出するために使用されます。
Edit
を呼び出した後も、編集バッファーは引き続き現在のレコードを表しますが、フィールド データ メンバーへの変更を受け入れる準備が整った状態になります。 レコードを変更するには、編集するフィールド データ メンバーの値を手動で設定します。 フィールドの実際のデータ値を指定する代わりに、SetFieldNull
を呼び出して Null 値を指定することもできます。 変更をコミットするには、Update
を呼び出します。
ヒント
AddNew
または Edit
モードから抜け出すには、AFX_MOVE_REFRESH パラメーターを指定して Move
を呼び出します。
Update
を呼び出す前提条件として、レコードセットが空であってはいけません。また、現在のレコードが削除されていないことも条件となります。 IsBOF
、IsEOF
、および IsDeleted
はすべて 0 を返します。
編集されたレコードに対して Update
を呼び出す場合:
ODBC ドライバーが
::SQLSetPos
ODBC API 関数をサポートしている場合、MFC はその関数を使用してデータ ソースにレコードを更新します。::SQLSetPos
を使用した場合、ドライバーは編集バッファーをサーバー上の対応するレコードと比較し、2 つが異なる場合にはサーバー上のレコードを更新します。::SQLSetPos
を使用した場合、MFC では、SQL ステートメントを作成して処理する必要がないので、より効率的にレコードを更新できます。または
::SQLSetPos
を使用できない場合、MFC では次の手順が実行されます。変更がなかった場合、
Update
は何も行いません。0 が返されます。変更がある場合は、
Update
は SQL UPDATE ステートメントを構築します。 UPDATE ステートメントに示される列は、変更されたフィールド データ メンバーに基づいて決まります。Update
は、変更をコミットします。UPDATE ステートメントが実行され、データ ソースでレコードが変更されますが、トランザクションが進行中の場合はコミットされません (トランザクションが更新に与える影響について詳しくは、「トランザクション: レコードセットからのトランザクション実行 (ODBC)」をご覧ください)。 ODBC にはレコードのコピーが保持されます (このコピーも変更されます)。AddNew
のプロセスとは異なり、このEdit
プロセスでは格納されているレコードは復元されません。 編集されたレコードが、そのまま現在のレコードとなります。
注意事項
Update
を呼び出してレコードセットを更新する前に、テーブルの主キーを構成するすべての列 (または、テーブルで一意のインデックスを構成するすべての列か、行を一意に識別するための十分な列) がレコードセットに含まれていることを確認してください。 場合によっては、フレームワークは、レコードセット内で選択されている列だけに基づいてテーブル内の更新するレコードを特定します。 必要なすべての列がない場合、テーブル内で複数のレコードが更新される可能性があります。 この場合は、Update
を呼び出した結果として例外がスローされます。ヒント
AddNew
またはEdit
を呼び出す前に、そのいずれかの関数を呼び出していて、それがUpdate
の呼び出しよりも前であった場合は、格納されたレコードによって編集バッファーが更新され、作業中の新しいレコードや編集済みレコードが置き換えられます。 この動作を行うと、AddNew
またはEdit
が中止され、新しい関数が開始されます。作業中のレコードに問題があることがはっきりしている場合は、Edit
またはAddNew
を再度呼び出してください。
レコードの削除
レコードセットからレコードを削除するには、レコードにスクロールし、レコードセットの Delete メンバー関数を呼び出す必要があります。 AddNew
や Edit
とは異なり、Delete
では、Update
への一致する呼び出しは必要ありません。
Delete
を呼び出す前提条件として、レコードセットは更新可能であり、1 つのレコード上である必要があります。 メンバー関数 CanUpdate
、IsBOF
、IsEOF
、および IsDeleted
を使用すると、これらの条件を確認できます。
Delete
を呼び出す場合:
ODBC ドライバーが
::SQLSetPos
ODBC API 関数をサポートしている場合、MFC はその関数を使用してデータ ソースにレコードを削除します。 通常は、::SQLSetPos
を使用する方が SQL を使用するよりも効率的です。または
::SQLSetPos
を使用できない場合、MFC では次の手順が実行されます。編集バッファー内の現在のレコードは、
AddNew
やEdit
の場合のようにはバックアップされません。Delete
が、レコードを削除する SQL DELETE ステートメントを構築します。編集バッファー内の現在のレコードは、
AddNew
やEdit
の場合のようには格納されません。Delete
が削除をコミットします。DELETE ステートメントが実行されます。 レコードはデータ ソースで削除済みとしてマークされます。レコードがスナップショットの場合は、ODBC でマークされます。削除されたレコードの値はレコードセットのフィールド データ メンバーに残りますが、フィールド データ メンバーは Null としてマークされ、レコードセットのメンバー関数
IsDeleted
は 0 以外の値を返します。
Note
レコードを削除したら、別のレコードまでスクロールし、編集バッファーに新しいレコードのデータを補充してください。
Delete
を再度呼び出したり、Edit
を呼び出したりするとエラーになります。
更新操作で使用される SQL ステートメントについて詳しくは、「SQL」をご覧ください。
関連項目
レコードセット (ODBC)
レコードセット: 更新処理の詳細 (ODBC)
レコード フィールド エクスチェンジ (RFX)