次の方法で共有


レコードセット: 更新処理の詳細 (ODBC)

このトピックの内容は、MFC ODBC クラスに該当します。

このトピックでは、次の内容について説明します。

  • トランザクションなどの操作が更新処理に及ぼす影響

  • 自分の更新処理とほかのユーザーによる更新処理

  • Update および Delete メンバー関数の詳細

注意

このトピックの内容は、バルク行フェッチが実装されていない CRecordset の派生オブジェクトを対象にしています。 バルク行フェッチを実装しているレコードセットには、一部の説明が該当しません。 たとえば、AddNewEditDelete、および Update の各メンバー関数を呼び出すことはできません。ただし、トランザクションの処理には支障ありません。 バルク行フェッチの詳細については、「レコードセット: バルク行フェッチ (ODBC)」を参照してください。

ほかの操作が更新処理に及ぼす影響

更新処理は、同時に進行しているトランザクションの影響を受けます。トランザクションが終了する前にレコードセットを閉じるか、スクロールすると、トランザクションの影響を受けます。

トランザクションが更新処理に及ぼす影響

AddNewEdit、および Delete の各動作に加え、CDatabaseBeginTransCommitTrans、および Rollback の各メンバー関数と CRecordset の更新関数の連係動作についても理解しておく必要があります。

既定では、AddNewEdit による変更内容は、Update を呼び出した時点でデータ ソースに反映されます。 Delete の呼び出しは、すぐに反映されます。 しかし、トランザクションを行うと、一連の呼び出しをバッチ処理として実行できます。 更新内容は、コミットするまではデータ ソースに反映されません。 更新内容を取り消すには、コミットせずに、トランザクションをロールバックします。

トランザクションの詳細については、「トランザクション (ODBC)」を参照してください。

レコードセットを閉じたときの更新処理

トランザクションの実行中に (つまり、CDatabase::CommitTrans または CDatabase::Rollback を呼び出す前に) レコードセットまたはそれに関連付けられた CDatabase オブジェクトを閉じると、(データベースのバック エンドが Microsoft Jet データベース エンジン以外の場合は) トランザクションが自動的にロールバックされます。

ヒント

Microsoft Jet データベース エンジンを使用する場合は、明示的なトランザクションの中でレコードセットを閉じても、このトランザクションをコミットまたはロールバックするまでは、変更した行および配置したロックが解除されません。 明示的な Jet トランザクションの内側で開いたレコードセットは、必ずトランザクションの内側で閉じることをお勧めします。また、外側で開いたレコードセットは、必ず外側で閉じることをお勧めします。

スクロールが更新処理に及ぼす影響

レコードセットを レコードセット: スクロール (ODBC)すると、エディット バッファーには新しい現在のレコードのフィールド値が格納されます (前のレコードは最初に格納されません)。 スクロールによって移動すると、削除されたレコードは飛ばされます (選択されません)。 AddNew または Edit の後で、UpdateCommitTrans、または Rollback を呼び出さずにスクロールすると、変更内容はすべて失われ、警告は行われません。新しいレコードがエディット バッファーに格納されます。 エディット バッファーには移動先のレコードの値が格納され、前のレコードの値は捨てられるため、データ ソースは変更されません。 この動作は、AddNewEdit の両方で行われます。

自分の更新処理とほかのユーザーによる更新処理

レコードセットを使ってデータを更新すると、ほかのユーザーにも影響を及ぼします。 同じように、ほかのユーザーが行った更新処理は、自分が使用中のレコードセットに影響します。

マルチ ユーザー環境では、自分のレコードセットとほかのユーザーのレコードセットが同じレコードを含んでいることがあります。 自分が取得する前にレコードに加えられた変更は、自分のレコードセットに反映されます。 ダイナセットでは、レコードにスクロールすると、そのたびにレコードが取得されるため、レコードにスクロールするたびに変更内容が反映されます。 一方、スナップショットでは、レコードに最初にスクロールしたときにだけレコードが取得されるため、それ以前の変更内容しか反映されません。

自分のレコードセットを開いた後に他のユーザーによって追加されたレコードは、クエリを再実行しない限り、自分のレコードセットには反映されません。 自分のレコードセットがダイナセットのときは、ほかのユーザーが既存のレコードに加えた編集結果は、そのレコードに移動 (スクロール) したときに反映されます。 自分のレコードセットがスナップショットのときは、クエリを再実行するまで編集結果は反映されません。 他のユーザーによって追加または削除されたレコードをスナップショットに反映させる場合や、他のユーザーによって追加されたレコードをダイナセットに反映させる場合は、CRecordset::Requery を呼び出す必要があります。 ダイナセットでは、ほかのユーザーによる削除は反映されます。 Requery を呼び出すと、自分で追加したレコードを確認することもできます。ただし、自分で行った削除を確認することはできません。

ヒント

スナップショット全体を一度にキャッシュするには、スナップショットを開いた直後に MoveLast を呼び出します。 次に、MoveFirst を呼び出してレコードセットを操作します。 MoveLast は、全レコードをスクロールするのと同じ動作を行いますが、一度に全レコードを取得します。 ただし、パフォーマンスが低下する場合があります。また、この機能が必要ないドライバーもあります。

同じように、自分の更新処理もほかのユーザーに影響します。

更新処理と削除処理の詳細

ここでは、UpdateDelete の動作について詳しく説明します。

更新の成功と失敗

Update が成功すると、AddNew モードまたは Edit モードが終了します。 AddNew モードまたは Edit モードを再開するには、AddNew または Edit を再び呼び出します。

Update が失敗 (FALSE が返るか、例外がスローされる) しても、AddNew モードまたは Edit モードは継続します。 失敗した場合は、以下のいずれかの処理を行うことができます。

  • フィールド データ メンバーの値を変えて Update を再実行します。

  • AddNew を呼び出してフィールド データ メンバーを Null 値にリセットしてから、フィールド データ メンバーの値を設定し、Update を再び呼び出します。

  • Edit を呼び出して、AddNew または Edit を呼び出す前のレコードセットの値を再読み込みします。次に、フィールド データ メンバーの値を設定し、Update を再び呼び出します。 Update が成功すると (AddNew 呼び出しの後を除いて)、フィールド データ メンバーには新しい値が設定されます。

  • Move を呼び出して (パラメーターとして AFX_MOVE_REFRESH または 0 を渡す場合も)、すべての変更内容を無効にして AddNew モードまたは Edit モードを終了します。

更新と削除

ここで説明する内容は、UpdateDelete の両方が対象です。

Update または Delete の操作では、一度に 1 レコードだけが更新されます。 更新されるのは、レコードセットのフィールド データ メンバーに値が保存されている現在のレコードです。 なんらかの理由により複数のレコードが更新されるか、どのレコードも更新されない場合は、次のどちらかの RETCODE 値を持つ例外がスローされます。

  • AFX_SQL_ERROR_NO_ROWS_AFFECTED

  • AFX_SQL_ERROR_MULTIPLE_ROWS_AFFECTED

これらの例外がスローされても、Update または Delete を呼び出したときの AddNew モードまたは Edit モードは継続します。 これらの例外は、通常、以下の場合にスローされます。 次の例外が最も頻繁に発生します。

  • AFX_SQL_ERROR_NO_ROWS_AFFECTED。共有ロック モードに設定しているときに、別のユーザーがレコードを変更したために、更新または削除するレコードをフレームワークが識別できなくなった場合。

  • AFX_SQL_ERROR_MULTIPLE_ROWS_AFFECTED。更新しようとしたテーブルに主キーまたは一意なインデックスがなく、レコードセット内の列数が不足していて、テーブルの行を特定できない場合。

参照

概念

レコードセット (ODBC)

レコードセット: レコード選択のしくみ (ODBC)

レコード フィールド エクスチェンジ (RFX)

SQL

例外処理 : データベースの例外