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

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

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

Note

このトピックの内容は、バルク行フェッチが実装されていない CRecordset の派生オブジェクトを対象にしています。 バルク行フェッチを実装している場合、一部の情報は適用されません。 たとえば、メンバー関数 AddNewEditDeleteUpdate を呼び出すことはできません。ただし、トランザクションは実行できます。 バルク行フェッチの詳細については、「レコードセット: バルク行フェッチ (ODBC)」を参照してください。

他の操作が更新に与える影響

更新は、更新時に有効なトランザクション、トランザクションの完了前にレコードセットを閉じること、およびトランザクションの完了前にスクロールすることによって影響を受けます。

トランザクションが更新に与える影響

AddNewEditDelete の動作を理解する以外に、CDatabase のメンバー関数 BeginTransCommitTransRollback が、CRecordset の更新関数とどのように連携するのかについて理解しておくことが重要です。

既定では、AddNewEdit の呼び出しは、Update を呼び出すとすぐにデータ ソースに反映されます。 Delete の呼び出しはすぐに有効になります。 ただし、トランザクションを確立し、そのような呼び出しのバッチを実行することができます。 コミットするまで、更新は確定していません。 気が変わった場合、トランザクションをコミットする代わりにロールバックできます。

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

レコードセットを閉じたときの更新への影響

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

注意事項

Microsoft Jet データベース エンジンを使っている場合は、明示的なトランザクションの内部にあるレコードセットを閉じても、明示的なトランザクションがコミットまたはロールバックされるまで、変更された行または設定されたロックは解放されません。 レコードセットを開く処理と閉じる処理の両方を、常に、明示的な Jet トランザクションの内部または外部で行うことをお勧めします。

スクロールが更新に与える影響

レコードセット内でスクロール (ODBC) を行うと、新しい現在の各レコードが編集バッファーに入れられます (最初に前のレコードが格納されることはありません)。 前に削除されたレコードはスクロールでスキップされます。 AddNew または Edit の呼び出しの後で、UpdateCommitTransRollback を先に呼び出さずにスクロールすると、新しいレコードが編集バッファーに取り込まれるので、変更は失われます (警告は表示されません)。 スクロール先のレコードで編集バッファーがいっぱいになると、格納されたレコードは解放され、データ ソースは変更されません。 これは、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 の Move を含む)、変更がフラッシュされて、有効な AddNew または Edit モードは終了します。

更新と削除

このセクションは、UpdateDelete の両方に適用されます。

Update または Delete 操作では、ただ 1 つのレコードのみを更新する必要があります。 そのレコードは現在のレコードであり、レコードセットのフィールドのデータ値に対応します。 何らかの理由で、影響を受けたレコードが 0 または複数の場合は、次のいずれかの 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
例外処理: データベースの例外