SQLSetPos 関数

準拠
導入されたバージョン: ODBC 1.0 Standards Compliance: ODBC

まとめ
SQLSetPos は、行セット内のカーソル位置を設定し、アプリケーションが行セット内のデータを更新したり、結果セット内のデータを更新または削除したりできます。

構文

  
SQLRETURN SQLSetPos(  
      SQLHSTMT        StatementHandle,  
      SQLSETPOSIROW   RowNumber,  
      SQLUSMALLINT    Operation,  
      SQLUSMALLINT    LockType);  

引数

StatementHandle
[入力]ステートメント ハンドル。

RowNumber
[入力] Operation 引数で指定された操作を実行する行セット内の行の位置。 RowNumber が 0 の場合、操作は行セット内のすべての行に適用されます。

詳細については、「コメント」を参照してください。

操作
[入力]実行する操作:

SQL_POSITION SQL_REFRESH SQL_UPDATE SQL_DELETE

注意

ODBC 3.x では、Operation 引数のSQL_ADD値は非推奨になりました。 ODBC 3.x ドライバーは、下位互換性のためにSQL_ADDをサポートする必要があります。 この機能は、 SQLBulkOperations の呼び出しと SQL_ADD の 操作 に置き換えられました。 ODBC 3.x アプリケーションが ODBC 2.x ドライバーで動作する場合、ドライバー マネージャーは、SQL_ADDの操作を使用して SQLBulkOperations への呼び出しを、SQL_ADDの操作を使用して SQLSetPos にマップします。

詳細については、「コメント」を参照してください。

LockType
[入力] Operation 引数で指定した操作を実行した後に行をロックする方法を指定します。

SQL_LOCK_NO_CHANGE SQL_LOCK_EXCLUSIVE SQL_LOCK_UNLOCK

詳細については、「コメント」を参照してください。

戻り値

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_NEED_DATA、SQL_STILL_EXECUTING、SQL_ERROR、またはSQL_INVALID_HANDLE。

診断

SQLSetPos がSQL_ERRORまたはSQL_SUCCESS_WITH_INFOを返す場合、関連付けられている SQLSTATE 値は、SQL_HANDLE_STMTの HandleTypeStatementHandleハンドルを使用して SQLGetDiagRec を呼び出すことによって取得できます。 次の表に、 SQLSetPos によって一般的に返される SQLSTATE 値の一覧を示し、この関数のコンテキストでそれぞれについて説明します。ドライバー マネージャーによって返される SQLSTATEs の説明の前に表記 "(DM)" が付きます。 特に記載がない限り、各 SQLSTATE 値に関連付けられている戻りコードはSQL_ERRORされます。

SQL_SUCCESS_WITH_INFOまたはSQL_ERROR (01xxx SQLSTATEs を除く) を返すことができるすべての SQLSTATEs について、1 つ以上の行でエラーが発生した場合はSQL_SUCCESS_WITH_INFOが返され、複数行操作の行はすべて返されず、1 行の操作でエラーが発生した場合はSQL_ERRORが返されます。

SQLSTATE エラー 説明
01000 一般的な警告 ドライバー固有の情報メッセージ。 (関数はSQL_SUCCESS_WITH_INFOを返します。
01001 カーソル操作の競合 Operation 引数がSQL_DELETEまたはSQL_UPDATEされ、行または複数の行が削除または更新されませんでした。 (複数の行の更新の詳細については、SQLSetStmtAttr のSQL_ATTR_SIMULATE_CURSOR属性の説明を参照してください)。(関数はSQL_SUCCESS_WITH_INFOを返します。

Operation 引数がSQL_DELETEまたはSQL_UPDATEされ、オプティミスティック コンカレンシーのために操作が失敗しました。 (関数はSQL_SUCCESS_WITH_INFOを返します。
01004 文字列データの右切り捨て Operation 引数がSQL_REFRESHされ、SQL_C_CHARまたはSQL_C_BINARYのデータ型を持つ列または列に対して文字列またはバイナリ データが返され、非空白文字または NULL 以外のバイナリ データが切り捨てられました。
01S01 行のエラー RowNumber 引数が 0 で、Operation 引数で指定された操作の実行中に 1 つ以上の行でエラーが発生しました。

(SQL_SUCCESS_WITH_INFOは、複数行操作の 1 つ以上の行でエラーが発生した場合は返され、1 行操作でエラーが発生した場合はSQL_ERRORが返されます)。

(この SQLSTATE は、SQLExtendedFetch の後に SQLSetPos が呼び出された場合にのみ返されます。ドライバーが ODBC 2.x ドライバーで、カーソル ライブラリが使用されていない場合)。
01S07 小数部の切り捨て Operation 引数がSQL_REFRESHされ、アプリケーション バッファーのデータ型がSQL_C_CHARまたはSQL_C_BINARYされず、1 つ以上の列のアプリケーション バッファーに返されたデータが切り捨てられました。 数値データ型の場合、数値の小数部が切り捨てられました。 時刻、タイムスタンプ、および時刻コンポーネントを含む間隔データ型の場合、時刻の小数部が切り捨てられました。

(関数はSQL_SUCCESS_WITH_INFOを返します。
07006 制限付きデータ型属性違反 結果セット内の列のデータ値を、SQLBindCol の呼び出しで TargetType で指定されたデータ型に変換できませんでした。
07009 記述子インデックスが無効です 引数 Operation がSQL_REFRESHまたはSQL_UPDATEされ、結果セット内の列数より大きい列番号で列がバインドされました。
21S02 派生テーブルの次数が列リストと一致しない 引数 Operation がSQL_UPDATEされ、すべての列が非バインド、読み取り専用、またはバインドされた長さ/インジケーター バッファーの値がSQL_COLUMN_IGNOREされたため、更新可能な列はありませんでした。
22001 文字列データ、右切り捨て Operation 引数がSQL_UPDATEされ、列に文字またはバイナリ値を割り当てると、非空白文字 (文字の場合) または null 以外 (バイナリ) 文字またはバイトが切り捨てられました。
22003 範囲外の数値 引数 Operation がSQL_UPDATEされ、結果セット内の列に数値を割り当てると、数値の部分全体 (小数部ではなく) が切り捨てられました。

引数 Operation がSQL_REFRESHされ、1 つ以上のバインドされた列の数値を返すと、有効桁数が失われた可能性があります。
22007 datetime 形式が無効です 引数 Operation がSQL_UPDATEされ、結果セット内の列に日付またはタイムスタンプ値を割り当て、年、月、または日のフィールドが範囲外になりました。

引数 Operation がSQL_REFRESHされ、1 つ以上のバインドされた列の日付またはタイムスタンプの値を返すと、年、月、または日のフィールドが範囲外になった可能性があります。
22008 日付/時刻フィールドオーバーフロー Operation 引数がSQL_UPDATEされ、結果セット内の列に送信されるデータに対する datetime 算術のパフォーマンスにより、結果の datetime フィールド (年、月、日、時間、分、または 2 番目のフィールド) がフィールドの許容範囲外であるか、グレゴリオ暦の日時の自然なルールに基づいて無効になりました。

Operation 引数がSQL_REFRESHされ、結果セットから取得されるデータに対する datetime 算術のパフォーマンスにより、結果の datetime フィールド (年、月、日、時間、分、または 2 番目のフィールド) がフィールドの許容範囲外であるか、グレゴリオ暦の日時の自然なルールに基づいて無効になりました。
22015 Interval フィールドオーバーフロー Operation 引数がSQL_UPDATEされ、正確な数値型または間隔 C 型をデータ型SQL間隔に割り当て、有効桁数が失われました。

Operation 引数がSQL_UPDATEされました。間隔SQL型に割り当てるときに、間隔SQL型の C 型の値が表されませんでした。

Operation 引数がSQL_REFRESHされ、正確な数値または間隔SQL型から間隔 C 型に割り当てられると、先頭のフィールドで有効桁数が失われました。

Operation 引数が REFRESH SQL_されました。間隔 C 型に割り当てるときに、間隔 C 型のSQL型の値の表現はありませんでした。
22018 キャスト指定の文字値が無効です Operation 引数がSQL_REFRESHされました。C 型は、正確または近似の数値、datetime、または間隔データ型でした。列のSQL型は文字データ型であり、列の値はバインドされた C 型の有効なリテラルではありません。

引数 Operation がSQL_UPDATEされました。SQL型は、正確または近似数値、datetime、または間隔データ型でした。C 型はSQL_C_CHARされました。列の値は、バインドされたSQL型の有効なリテラルではありません。
23000 整合性制約違反 引数 Operation がSQL_DELETEまたはSQL_UPDATEされ、整合性制約に違反しました。
24000 カーソル状態が無効 StatementHandle が実行された状態でしたが、結果セットが StatementHandle に関連付けられなかった。

(DM) StatementHandle でカーソルが開かれていましたが、 SQLFetch または SQLFetchScroll が呼び出されませんでした。

StatementHandle でカーソルが開き、SQLFetch または SQLFetchScroll が呼び出されましたが、カーソルは結果セットの開始前または結果セットの末尾の後に配置されました。

引数 Operation はSQL_DELETE、SQL_REFRESH、またはSQL_UPDATEであり、カーソルは結果セットの開始前または結果セットの末尾の後に配置されました。
40001 シリアル化エラー リソースが別のトランザクションとデッドロックしたため、トランザクションがロールバックされました。
40003 ステートメントの入力候補が不明 この関数の実行中に関連付けられている接続が失敗し、トランザクションの状態を特定できません。
42000 構文エラーまたはアクセス違反 ドライバーは、引数 Operation で要求された操作を実行するために、必要に応じて行をロックできませんでした。

ドライバーは、引数 LockType で要求された行をロックできませんでした。
44000 WITH CHECK OPTION 違反 Operation 引数がSQL_UPDATEされ、更新の影響を受ける 1 つ以上の行が表示テーブルに存在しなくなるよう、WITH CHECK OPTION を指定して作成された表示テーブルまたは表示テーブルから派生したテーブルに対して更新が実行されました。
HY000 一般的なエラー 特定の SQLSTATE がなく、実装固有の SQLSTATE が定義されていないエラーが発生しました。 *MessageText バッファー内の SQLGetDiagRec によって返されるエラー メッセージは、エラーとその原因について説明します。
HY001 メモリ割り当てエラー ドライバーは、関数の実行または完了をサポートするために必要なメモリを割り当てませんでした。
HY008 操作が取り消されました StatementHandle に対して非同期処理が有効になりました。 関数が呼び出され、実行が完了する前に、 SqlCancel または SQLCancelHandleStatementHandle で呼び出され、その関数が StatementHandle で再度呼び出されました。

関数が呼び出され、実行が完了する前に、マルチスレッド アプリケーションの別のスレッドから StatementHandleSQLCancel または SQLCancelHandle が呼び出されました。
HY010 関数シーケンス エラー (DM) StatementHandle に関連付けられている接続ハンドルに対して非同期に実行される関数が呼び出されました。 この非同期関数は、SQLSetPos 関数が呼び出されたときにまだ実行されていました。

(DM) 指定された StatementHandle が実行された状態にありません。 この関数は、 SQLExecDirectSQLExecute、またはカタログ関数を最初に呼び出さずに呼び出されました。

(DM) 非同期で実行される関数 (この関数ではなく) が StatementHandle に対して呼び出され、この関数が呼び出されたときにまだ実行されていました。

(DM) SQLExecuteSQLExecDirectSQLBulkOperations、または SQLSetPosStatementHandle に対して呼び出され、SQL_NEED_DATA返されました。 この関数は、実行中のすべてのデータ パラメーターまたは列に対してデータが送信される前に呼び出されました。

(DM) ドライバーは ODBC 2.x ドライバーで、SQLSetPosSQLFetch の呼び出し後に StatementHandle に対して呼び出されました。
HY011 属性を今すぐ設定できない (DM) ドライバーは ODBC 2.x ドライバーでした。SQL_ATTR_ROW_STATUS_PTRステートメント属性が設定されました。SQLSetPos は、SQLFetchSQLFetchScroll、または SQLExtendedFetch が呼び出される前に呼び出されました。
HY013 メモリ管理エラー 基になるメモリ オブジェクトにアクセスできなかったため、メモリの状態が低いため、関数呼び出しを処理できませんでした。
HY090 文字列またはバッファーの長さが無効です Operation 引数がSQL_UPDATEされ、データ値が null ポインターで、列の長さの値が 0、SQL_DATA_AT_EXEC、SQL_COLUMN_IGNORE、SQL_NULL_DATA、または SQL_LEN_DATA_AT_EXEC_OFFSET 以下でした。

Operation 引数がSQL_UPDATEされました。データ値が null ポインターではありません。C データ型がSQL_C_BINARYまたはSQL_C_CHAR。列の長さの値は 0 未満でしたが、SQL_DATA_AT_EXEC、SQL_COLUMN_IGNORE、SQL_NTS、またはSQL_NULL_DATAと等しくないか、またはSQL_LEN_DATA_AT_EXEC_OFFSET以下でした。

長さ/インジケーター バッファー内の値がSQL_DATA_AT_EXECされました。SQL型は、SQL_LONGVARCHAR、SQL_LONGVARBINARY、または長いデータ ソース固有のデータ型のいずれかであり、SQLGetInfo のSQL_NEED_LONG_DATA_LEN情報型は "Y" でした。
HY092 無効な属性識別子 (DM) Operation 引数に指定された値が無効です。

(DM) LockType 引数に指定された値が無効です。

Operation 引数がSQL_UPDATEまたはSQL_DELETEされ、SQL_ATTR_CONCURRENCYステートメント属性がSQL_ATTR_CONCUR_READ_ONLYされました。
HY107 範囲外の行の値 引数 RowNumber に指定された値が、行セット内の行数より大きかった。
HY109 カーソル位置が無効です StatementHandle に関連付けられているカーソルは前方専用として定義されているため、カーソルを行セット内に配置できませんでした。 SQLSetStmtAttr のSQL_ATTR_CURSOR_TYPE属性の説明を参照してください。

Operation 引数がSQL_UPDATE、SQL_DELETE、またはSQL_REFRESHであり、RowNumber 引数によって識別された行が削除されたか、フェッチされていませんでした。

(DM) RowNumber 引数が 0 で、 Operation 引数がSQL_POSITIONされました。

SQLSetPos は、 SQLBulkOperations が呼び出された後、および SQLFetchScroll または SQLFetch が呼び出される前に呼び出されました。
HY117 不明なトランザクション状態のため、接続が中断されます。 切断および読み取り専用の関数のみが許可されます。 (DM) 中断状態の詳細については、 SQLEndTran 関数を参照してください。
HYC00 省略可能な機能が実装されていません ドライバーまたはデータ ソースは、Operation 引数または LockType 引数で要求された操作をサポートしていません。
HYT00 タイムアウトに達しました データ ソースが結果セットを返す前に、クエリのタイムアウト期間の有効期限が切れています。 タイムアウト期間は、SQL_ATTR_QUERY_TIMEOUTの属性を持つ SQLSetStmtAttr を使用して設定されます。
HYT01 接続のタイムアウト データ ソースが要求に応答する前に、接続タイムアウト期間の有効期限が切れています。 接続タイムアウト期間は、 SQL_ATTR_CONNECTION_TIMEOUT SQLSetConnectAttr を介して設定されます。
IM001 ドライバーは、この関数をサポートしていません (DM) StatementHandle に関連付けられているドライバーは、関数をサポートしていません。
IM017 非同期通知モードでポーリングが無効になっている 通知モデルが使用されるたびに、ポーリングは無効になります。
IM018 SQLCompleteAsync は、このハンドルに対する前の非同期操作を完了するために呼び出されていません。 ハンドルの前の関数呼び出しがSQL_STILL_EXECUTINGを返し、通知モードが有効になっている場合は、処理後の処理を実行して操作を完了するには、そのハンドルで SQLCompleteAsync を呼び出す必要があります。

コメント

注意事項

ステートメントの状態については、 SQLSetPos を呼び出すことができること、および ODBC 2.x アプリケーションとの互換性のために何を行う必要があるかについては、「 ブロック カーソル、スクロール可能なカーソル、および下位互換性」を参照してください。

RowNumber 引数

RowNumber 引数は、Operation 引数で指定された操作を実行する行セット内の行の数を指定します。 RowNumber が 0 の場合、操作は行セット内のすべての行に適用されます。 RowNumber は、0 から行セット内の行数までの値である必要があります。

注意

C 言語では、配列は 0 から始まります。 RowNumber 引数は 1 から始まります。 たとえば、行セットの 5 行目を更新するために、アプリケーションは配列インデックス 4 で行セット バッファーを変更しますが、 RowNumber は 5 を指定します。

すべての操作は、 RowNumber で指定された行にカーソルを置きます。 次の操作にはカーソル位置が必要です。

  • 配置された更新ステートメントと delete ステートメント。

  • SQLGetData の呼び出し。

  • SQL_DELETE、SQL_REFRESH、およびSQL_UPDATEオプションを使用して SQLSetPos を呼び出します。

たとえば、操作がSQL_DELETEの SQLSetPos の呼び出しに対して RowNumber が 2 の場合、カーソルは行セットの 2 行目に配置され、その行は削除されます。 2 行目の実装行状態配列 (SQL_ATTR_ROW_STATUS_PTR ステートメント属性が指す) のエントリがSQL_ROW_DELETEDに変更されます。

アプリケーションは、 SQLSetPos を呼び出すときにカーソル位置を指定できます。 一般に、 SQLSetPos は、配置された更新または削除ステートメントを実行する前にカーソルを配置するか、 SQLGetData を呼び出す前に、SQL_POSITIONまたはSQL_REFRESH操作で SQLSetPos を呼び出します。

Operation 引数

Operation 引数は、次の操作をサポートします。 データ ソースでサポートされているオプションを特定するために、アプリケーションは、(カーソルの種類に応じて) SQL_DYNAMIC_CURSOR_ATTRIBUTES1、SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1、SQL_KEYSET_CURSOR_ATTRIBUTES1、またはSQL_STATIC_CURSOR_ATTRIBUTES1情報の種類を使用して SQLGetInfo を呼び出します。

操作

引数
操作
SQL_POSITION ドライバーは、 RowNumber で指定された行にカーソルを置きます。

SQL_POSITION 操作では、SQL_ATTR_ROW_OPERATION_PTR ステートメント属性が指す行状態配列の内容は無視されます。
SQL_REFRESH ドライバーは 、RowNumber で指定された行にカーソルを置き、その行の行セット バッファー内のデータを更新します。 ドライバーが行セット バッファー内のデータを返す方法の詳細については、 SQLBindCol の行方向と列方向のバインドの説明を参照してください。

SQL_REFRESHの操作を含む SQLSetPos は、現在フェッチされている行セット内の行の状態と内容を更新します。 これには、ブックマークの更新が含まれます。 バッファー内のデータは更新されますが、再フェッチされないため、行セットのメンバーシップは固定されています。 これは、 sqlFetchScroll の呼び出しで実行される更新とは異なり、 fetchOrientation が SQL_FETCH_RELATIVE で RowNumber が 0 で、結果セットから行セットが再フェッチされるため、追加されたデータを表示したり、ドライバーとカーソルで操作がサポートされている場合に削除されたデータを削除したりできます。

SQLSetPos を使用して正常に更新された場合、SQL_ROW_DELETEDの行の状態は変更されません。 行セット内の削除された行は、次のフェッチまで削除済みとしてマークされ続けます。 カーソルがパッキングをサポートしている (後続の SQLFetch または SQLFetchScroll が削除された行を返さない) 場合、行は次のフェッチ時に消えます。

SQLSetPos を使用した更新が実行されると、追加された行は表示されません。 この動作は、fetchType が SQL_FETCH_RELATIVE で RowNumber が 0 である SQLFetchScroll とは異なります。これは、現在の行セットも更新されますが、カーソルでこれらの操作がサポートされている場合は、追加されたレコードを表示したり、削除されたレコードをパックしたりします。

SQLSetPos を使用して正常に更新されると、行の状態SQL_ROW_ADDEDがSQL_ROW_SUCCESSに変更されます (行の状態配列が存在する場合)。

SQLSetPos を使用して正常に更新されると、SQL_ROW_UPDATEDの行の状態が行の新しい状態に変更されます (行の状態配列が存在する場合)。

行に対する SQLSetPos 操作でエラーが発生した場合、行の状態はSQL_ROW_ERRORに設定されます (行ステータス配列が存在する場合)。

SQL_CONCUR_ROWVERまたはSQL_CONCUR_VALUESのSQL_ATTR_CONCURRENCYステートメント属性で開かれたカーソルの場合、 SQLSetPos を使用した更新では、データ ソースで使用されるオプティミスティック コンカレンシー値が更新され、行が変更されたことを検出する場合があります。 この場合、行セット バッファーがサーバーから更新されるたびに、カーソルのコンカレンシーを確保するために使用される行のバージョンまたは値が更新されます。 これは、更新される各行に対して発生します。

SQL_ATTR_ROW_OPERATION_PTR ステートメント属性が指す行状態配列の内容は、SQL_REFRESH 操作では無視されます。
SQL_UPDATE ドライバーは、RowNumber で指定された行にカーソルを置き、行セット バッファー内の値 (SQLBindColTargetValuePtr 引数) を使用して、基になるデータ行を更新します。 長さ/インジケーター バッファー (SQLBindColStrLen_or_IndPtr引数) からデータの長さを取得します。 列の長さがSQL_COLUMN_IGNOREの場合、列は更新されません。 行を更新した後、ドライバーは行ステータス配列の対応する要素をSQL_ROW_UPDATEDまたはSQL_ROW_SUCCESS_WITH_INFOに変更します (行ステータス配列が存在する場合)。

SQL_UPDATEの Operation 引数を持つ SQLSetPos が、重複する列を含むカーソルで呼び出された場合の動作はドライバーによって定義されます。 ドライバーは、ドライバー定義の SQLSTATE を返したり、結果セットに表示される最初の列を更新したり、他のドライバー定義の動作を実行したりできます。

SQL_ATTR_ROW_OPERATION_PTR ステートメント属性が指す行操作配列を使用して、一括更新中に現在の行セット内の行を無視する必要があることを示すことができます。 詳細については、この関数リファレンスで後述する「Status and Operation Arrays」を参照してください。
SQL_DELETE ドライバーは 、RowNumber で指定された行にカーソルを置き、基になるデータ行を削除します。 行ステータス配列の対応する要素がSQL_ROW_DELETEDに変更されます。 行が削除された後は、位置指定された更新ステートメントと削除ステートメント、SQLGetData の呼び出し、および Operation がSQL_POSITION以外の何かに設定された SQLSetPos の呼び出しは、行に対して無効になります。 パッキングをサポートするドライバーの場合、データ ソースから新しいデータを取得すると、行がカーソルから削除されます。

行を表示したままにするかどうかは、カーソルの種類によって異なります。 たとえば、削除された行は静的カーソルとキーセット駆動型カーソルには表示されますが、動的カーソルには表示されません。

SQL_ATTR_ROW_OPERATION_PTR ステートメント属性が指す行操作配列を使用して、一括削除中に現在の行セット内の行を無視する必要があることを示すことができます。 詳細については、この関数リファレンスで後述する「Status and Operation Arrays」を参照してください。

LockType 引数

LockType 引数は、アプリケーションがコンカレンシーを制御する方法を提供します。 ほとんどの場合、コンカレンシー レベルとトランザクションをサポートするデータ ソースでは、 LockType 引数のSQL_LOCK_NO_CHANGE値のみがサポートされます。 LockType 引数は、通常、ファイル ベースのサポートにのみ使用されます。

LockType 引数は、SQLSetPos が実行された後の行のロック状態を指定します。 ドライバーは、要求された操作を実行するか、 LockType 引数を満たすために行をロックできない場合は、SQL_ERRORと SQLSTATE 42000 (構文エラーまたはアクセス違反) を返します。

LockType 引数は 1 つのステートメントに対して指定されますが、ロックは接続上のすべてのステートメントに同じ特権を付与します。 特に、接続上の 1 つのステートメントによって取得されるロックは、同じ接続上の別のステートメントによってロック解除できます。

SQLSetPos でロックされた行は、LockType が SQL_LOCK_UNLOCK に設定された行に対して SQLSetPos を呼び出すまで、またはアプリケーションがステートメントに対して SQLFreeHandle を呼び出すまで、または SQL_CLOSE オプションを指定して SQLFreeStmt を呼び出すまでロックされたままになります。 トランザクションをサポートするドライバーの場合、アプリケーションが SQLEndTran を呼び出して接続でトランザクションをコミットまたはロールバックすると、SQLSetPos によってロックされた行がロック解除されます (SQLGetInfo によって返されるSQL_CURSOR_COMMIT_BEHAVIORおよびSQL_CURSOR_ROLLBACK_BEHAVIOR情報の種類によって示されるように、トランザクションがコミットまたはロールバックされたときにカーソルが閉じられる場合)。

LockType 引数は、次の種類のロックをサポートします。 データ ソースでサポートされているロックを特定するために、アプリケーションは、(カーソルの種類に応じて) SQL_DYNAMIC_CURSOR_ATTRIBUTES1、SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1、SQL_KEYSET_CURSOR_ATTRIBUTES1、またはSQL_STATIC_CURSOR_ATTRIBUTES1情報の種類を使用して SQLGetInfo を呼び出します。

LockType 引数 ロックの種類
SQL_LOCK_NO_CHANGE ドライバーまたはデータ ソースは、 SQLSetPos が呼び出される前と同じロックまたはロック解除された状態であることを確認します。 LockType のこの値を使用すると、明示的な行レベルのロックをサポートしていないデータ ソースは、現在のコンカレンシーレベルとトランザクション分離レベルで必要なロックを使用できます。
SQL_LOCK_EXCLUSIVE ドライバーまたはデータ ソースは、行を排他的にロックします。 別の接続または別のアプリケーションのステートメントを使用して、行のロックを取得することはできません。
SQL_LOCK_UNLOCK ドライバーまたはデータ ソースによって行のロックが解除されます。

ドライバーがSQL_LOCK_EXCLUSIVEをサポートしているが、SQL_LOCK_UNLOCKをサポートしていない場合、ロックされている行は、前の段落で説明した関数呼び出しのいずれかが発生するまでロックされたままになります。

ドライバーがSQL_LOCK_EXCLUSIVEをサポートしているが、SQL_LOCK_UNLOCKをサポートしていない場合、アプリケーションがステートメントの SQLFreeHandle を呼び出すか、SQL_CLOSE オプションを指定して SQLFreeStmt を呼び出すまで、ロックされている行はロックされたままになります。 ドライバーがトランザクションをサポートし、トランザクションのコミットまたはロールバック時にカーソルを閉じると、アプリケーションは SQLEndTran を呼び出します。

SQLSetPos の更新操作と削除操作の場合、アプリケーションは LockType 引数を次のように使用します。

  • 取得後に行が変更されないことを保証するために、アプリケーションは、Operation を SQL_REFRESH に設定し、LockType を SQL_LOCK_EXCLUSIVE に設定して SQLSetPos を呼び出します。

  • アプリケーションが LockType をSQL_LOCK_NO_CHANGEに設定した場合、ドライバーは、アプリケーションがSQL_ATTR_CONCURRENCYステートメント属性にSQL_CONCUR_LOCK指定した場合にのみ、更新または削除操作が成功することを保証します。

  • アプリケーションで SQL_ATTR_CONCURRENCY ステートメント属性のSQL_CONCUR_ROWVERまたはSQL_CONCUR_VALUESを指定した場合、ドライバーは行のバージョンまたは値を比較し、アプリケーションが行をフェッチしてから行が変更された場合は操作を拒否します。

  • アプリケーションで SQL_ATTR_CONCURRENCY ステートメント属性のSQL_CONCUR_READ_ONLYが指定されている場合、ドライバーは更新操作または削除操作を拒否します。

SQL_ATTR_CONCURRENCY ステートメント属性の詳細については、「 SQLSetStmtAttr」を参照してください。

状態配列と操作配列

SQLSetPos を呼び出すときは、次の状態配列と操作配列が使用されます。

  • 行ステータス配列 (IRD および SQL_ATTR_ROW_STATUS_ARRAY ステートメント属性の SQL_DESC_ARRAY_STATUS_PTR フィールドで示される) には、行セット内のデータ行ごとに状態値が含まれます。 ドライバーは、SQLFetch、SQLFetchScrollSQLBulkOperations、または SQLSetPos の呼び出し後に、この配列の状態値を設定します。 この配列は、SQL_ATTR_ROW_STATUS_PTR ステートメント属性によって指されます。

  • 行操作配列 (ARD および SQL_ATTR_ROW_OPERATION_ARRAY ステートメント属性の SQL_DESC_ARRAY_STATUS_PTR フィールドが指すように) には、一括操作に対する SQLSetPos の呼び出しが無視されるか実行されるかを示す行セット内の各行の値が含まれています。 配列内の各要素は、SQL_ROW_PROCEED (既定値) またはSQL_ROW_IGNOREに設定されます。 この配列は、SQL_ATTR_ROW_OPERATION_PTR ステートメント属性によって指されます。

状態配列と操作配列内の要素の数は、(SQL_ATTR_ROW_ARRAY_SIZE ステートメント属性で定義されている) 行セット内の行数と等しい必要があります。

行ステータス配列の詳細については、 SQLFetch を参照してください。 行操作配列の詳細については、このセクションで後述する「一括操作での行の無視」を参照してください。

SQLSetPos の使用

アプリケーションが SQLSetPos を呼び出す前に、次の一連の手順を実行する必要があります。

  1. アプリケーションで操作が SQL_UPDATE に設定された SQLSetPos を呼び出す場合は、各列に対して SQLBindCol (または SQLSetDescRec) を呼び出して、そのデータ型と列のデータと長さのバインド バッファーを指定します。

  2. アプリケーションが SQLSetPos を呼び出し、 Operation が SQL_DELETE またはSQL_UPDATEに設定されている場合は、 SQLColAttribute を 呼び出して、削除または更新する列が更新可能であることを確認します。

  3. SQLExecDirectSQLExecute、またはカタログ関数を呼び出して、結果セットを作成します。

  4. SQLFetch または SQLFetchScroll を呼び出してデータを取得します。

SQLSetPos の使用の詳細については、「SQLSetPos を使用したデータの更新」を参照してください。

SQLSetPos を使用したデータの削除

SQLSetPos を使用してデータを削除するために、アプリケーションは SQLSetPos を呼び出し、RowNumber を削除する行の数に設定し、操作をSQL_DELETEに設定します。

データが削除されると、ドライバーは、適切な行の実装行の状態配列の値をSQL_ROW_DELETED (またはSQL_ROW_ERROR) に変更します。

SQLSetPos を使用したデータの更新

アプリケーションは、バインドされたデータ バッファー内または SQLPutData への 1 つ以上の呼び出しを使用して、列の値を渡すことができます。 SQLPutData でデータが渡される列は、実行時データと呼ばれます。 これらは一般的に、SQL_LONGVARBINARY列とSQL_LONGVARCHAR列のデータを送信するために使用され、他の列と混在させることができます。

SQLSetPos を使用してデータを更新するには、次の手順を実行します。

  1. SQLBindCol でバインドされたデータ バッファーと長さ/インジケーター バッファーに値を配置します。

    • 通常の列の場合、アプリケーションは *TargetValuePtr バッファーに新しい列値を配置し、その値の長さを *StrLen_or_IndPtr バッファーに配置します。 行を更新しない場合、アプリケーションは行操作配列のその行の要素にSQL_ROW_IGNOREを配置します。

    • 実行時データ列の場合、アプリケーションはアプリケーション定義値 (列番号など) を *TargetValuePtr バッファーに配置します。 この値は、後で列を識別するために使用できます。

      アプリケーションは、SQL_LEN_DATA_AT_EXEC(length) マクロの結果を *StrLen_or_IndPtr バッファーに配置します。 列のSQLデータ型がSQL_LONGVARBINARY、SQL_LONGVARCHAR、または長いデータ ソース固有のデータ型であり、ドライバーが SQLGetInfo のSQL_NEED_LONG_DATA_LEN情報型の "Y" を返す場合、length はパラメーターに送信されるデータのバイト数です。それ以外の場合は負以外の値にする必要があり、無視されます。

  2. SqlSetPos を呼び出し、Operation 引数を SQL_UPDATE に設定してデータ行を更新します。

    • 実行中のデータ列がない場合、プロセスは完了です。

    • 実行中のデータ列がある場合、関数はSQL_NEED_DATAを返し、手順 3 に進みます。

  3. SQLParamData を呼び出して、処理中の最初のデータ実行時列の *TargetValuePtr バッファーのアドレスを取得します。 SQLParamData はSQL_NEED_DATAを返します。 アプリケーションは、 *TargetValuePtr バッファーからアプリケーション定義値を取得します。

    注意

    実行時データ パラメーターは実行時データ列に似ていますが、 SQLParamData によって返される値はそれぞれ異なります。

    注意

    実行時データ パラメーターは、SQLExecDirect または SQLExecute でステートメントを実行するときに SQLPutData でデータが送信される、SQL ステートメント内のパラメーターです。 SQLBindParameter または SQLSetDescRec を使用して記述子を設定することによってバインドされます。 SQLParamData によって返される値は、ParameterValuePtr 引数の SQLBindParameter に渡される 32 ビット値です。

    注意

    実行時のデータ列は、SQLSetPos で行が更新されたときに SQLPutData でデータが送信される行セット内の列です。 これらは SQLBindCol でバインドされます。 SQLParamData によって返される値は、処理中の *TargetValuePtr バッファー内の行のアドレスです。

  4. SQLPutData を 1 回以上呼び出して、列のデータを送信します。 SQLPutData で指定された *TargetValuePtr バッファーですべてのデータ値を返すことができない場合は、複数の呼び出しが必要です。同じ列に対する SQLPutData への複数の呼び出しは、文字、バイナリ、またはデータ ソース固有のデータ型を持つ列に文字 C データを送信する場合、またはバイナリ C データを文字、バイナリ、またはデータ ソース固有のデータ型を持つ列に送信する場合にのみ許可されます。

  5. SQLParamData をもう一度呼び出して、列に対してすべてのデータが送信されたことを通知します。

    • 実行中のデータ列が多い場合、 SQLParamData は、SQL_NEED_DATAと、処理される次の実行時データ列の TargetValuePtr バッファーのアドレスを返します。 アプリケーションは、手順 4 と 5 を繰り返します。

    • 実行中のデータ列がこれ以上ない場合、プロセスは完了です。 ステートメントが正常に実行された場合、 SQLParamData はSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOを返します。実行が失敗した場合は、SQL_ERRORが返されます。 この時点で、 SQLParamData は SQLSetPos から返すことができる任意の SQLSTATE を返すことができます。

データが更新された場合、ドライバーは、適切な行の実装行の状態配列の値をSQL_ROW_UPDATEDに変更します。

操作が取り消されたか、 SQLParamData または SQLPutData でエラーが発生した場合、 SQLSetPos がSQL_NEED_DATAを返した後で、実行中のすべての列に対してデータが送信される前に、アプリケーションはステートメントまたはステートメントに関連付けられている接続に対して SQLCancelSQLGetDiagFieldSQLGetDiagRecSQLGetFunctionsSQLParamData、または SQLPutData のみを呼び出すことができます。 ステートメントまたはステートメントに関連付けられている接続に対して他の関数を呼び出した場合、関数はSQL_ERRORおよび SQLSTATE HY010 (関数シーケンス エラー) を返します。

実行中のデータ列のデータがまだドライバーに必要な状態で、アプリケーションが SQLCancel を呼び出す場合、ドライバーは操作を取り消します。 その後、アプリケーションは SQLSetPos をもう一度呼び出すことができます。取り消しは、カーソルの状態や現在のカーソル位置には影響しません。

カーソルに関連付けられているクエリ仕様の SELECT リストに同じ列への参照が複数含まれている場合、エラーが生成されるか、ドライバーが重複した参照を無視して要求された操作を実行するかはドライバー定義です。

一括操作の実行

RowNumber 引数が 0 の場合、ドライバーは、ステートメント属性が指す行操作配列内のフィールドにSQL_ROW_PROCEED値を持つ行セット内のすべての行に対して、Operation 引数で指定された操作SQL_ATTR_ROW_OPERATION_PTR実行します。 これは、SQL_DELETE、SQL_REFRESH、またはSQL_UPDATEの Operation 引数の RowNumber 引数の有効な値ですが、SQL_POSITIONではありません。 SQL_POSITIONの操作RowNumber が 0 に等しい SQLSetPos は、SQLSTATE HY109 (無効なカーソル位置) を返します。

SQLSTATE HYT00 (タイムアウト期限切れ) など、行セット全体に関連するエラーが発生した場合、ドライバーはSQL_ERRORと適切な SQLSTATE を返します。 行セット バッファーの内容は未定義であり、カーソル位置は変更されません。

1 つの行に関連するエラーが発生した場合、ドライバーは次の操作を行います。

  • SQL_ATTR_ROW_STATUS_PTR ステートメント属性が指す行状態配列の行の要素をSQL_ROW_ERRORに設定します。

  • エラー キューにエラーに対して 1 つ以上の追加の SQLSTATEs をポストし、診断データ構造のSQL_DIAG_ROW_NUMBER フィールドを設定します。

エラーまたは警告を処理した後、ドライバーが行セット内の残りの行の操作を完了すると、SQL_SUCCESS_WITH_INFOが返されます。 したがって、エラーを返した行ごとに、エラー キューに 0 個以上の追加 SQLSTATEs が含まれます。 ドライバーは、エラーまたは警告を処理した後に操作を停止した場合は、SQL_ERRORを返します。

SQLSTATE 01004 (データ切り捨て) などの警告がドライバーから返された場合、特定の行に適用されるエラー情報を返す前に、行セット全体または行セット内の不明な行に適用される警告が返されます。 特定の行に関する警告と、それらの行に関するその他のエラー情報が返されます。

RowNumber が 0 に等しく、Operation がSQL_UPDATE、SQL_REFRESH、またはSQL_DELETEの場合、SQLSetPos が操作する行の数は、SQL_ATTR_ROWS_FETCHED_PTR ステートメント属性によって指されます。

RowNumber が 0 に等しく、Operation がSQL_DELETE、SQL_REFRESH、またはSQL_UPDATEの場合、操作の後の現在の行は、操作の前の現在の行と同じです。

一括操作の行を無視する

行操作配列を使用して、 SQLSetPos を使用した一括操作中に、現在の行セット内の行を無視する必要があることを示すことができます。 一括操作中に 1 つ以上の行を無視するようにドライバーに指示するには、アプリケーションで次の手順を実行する必要があります。

  1. SQLSetStmtAttr を呼び出して、SQLUSMALLINT の配列を指すSQL_ATTR_ROW_OPERATION_PTRステートメント属性を設定します。 このフィールドは、 SQLSetDescField を呼び出して ARD のSQL_DESC_ARRAY_STATUS_PTR ヘッダー フィールドを設定することによっても設定できます。これには、アプリケーションが記述子ハンドルを取得する必要があります。

  2. 行操作配列の各要素を、次の 2 つの値のいずれかに設定します。

    • SQL_ROW_IGNORE、一括操作で行が除外されることを示します。

    • SQL_ROW_PROCEED、行が一括操作に含まれていることを示します。 (これは既定値です)。

  3. SQLSetPos を呼び出して一括操作を実行します。

行操作配列には、次の規則が適用されます。

  • SQL_ROW_IGNOREとSQL_ROW_PROCEEDは、SQL_DELETEまたはSQL_UPDATEの操作で SQLSetPos を使用する一括 操作 にのみ影響します。 SQL_REFRESHまたはSQL_POSITIONの操作を使用した SQLSetPos の呼び出しには影響しません。

  • ポインターは既定で null に設定されます。

  • ポインターが null の場合、すべての要素がSQL_ROW_PROCEEDに設定されているかのように、すべての行が更新されます。

  • 要素をSQL_ROW_PROCEEDに設定しても、その特定の行に対して操作が実行されるわけではありません。 たとえば、行セット内の特定の行の状態がSQL_ROW_ERROR場合、ドライバーは、アプリケーションがSQL_ROW_PROCEED指定したかどうかに関係なく、その行を更新できない可能性があります。 操作が成功したかどうかを確認するには、アプリケーションで常に行の状態配列を確認する必要があります。

  • SQL_ROW_PROCEEDは、ヘッダー ファイルで 0 として定義されます。 アプリケーションは、すべての行を処理するために、行操作配列を 0 に初期化できます。

  • 行操作配列の要素番号 "n" が SQL_ROW_IGNORE に設定され、 SQLSetPos が呼び出されて一括更新または削除操作が実行された場合、行セット内の n 番目の行は SQLSetPos の呼び出し後も変更されません。

  • アプリケーションは、読み取り専用列を自動的にSQL_ROW_IGNOREに設定する必要があります。

一括操作での列の無視

1 つ以上の読み取り専用列に対して更新を試行することによって生成される不要な処理診断を回避するために、アプリケーションはバインドされた長さ/インジケーター バッファーの値をSQL_COLUMN_IGNOREに設定できます。 詳細については、「 SQLBindCol」を参照してください。

コード例

次の例では、アプリケーションを使用すると、ユーザーは ORDERS テーブルを参照し、注文の状態を更新できます。 カーソルは、行セット サイズが 20 のキーセット駆動型であり、行バージョンを比較するオプティミスティック コンカレンシー制御を使用します。 各行セットがフェッチされると、アプリケーションによって出力され、ユーザーは注文の状態を選択して更新できます。 アプリケーションでは 、SQLSetPos を使用して、選択した行にカーソルを置き、行の位置指定された更新を実行します。 (わかりやすくするため、エラー処理は省略されています)。

#define ROWS 20  
#define STATUS_LEN 6  
  
SQLCHAR        szStatus[ROWS][STATUS_LEN], szReply[3];  
SQLINTEGER     cbStatus[ROWS], cbOrderID;  
SQLUSMALLINT   rgfRowStatus[ROWS];  
SQLUINTEGER    sOrderID, crow = ROWS, irow;  
SQLHSTMT       hstmtS, hstmtU;  
  
SQLSetStmtAttr(hstmtS, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) rgfRowStatus, 0);  
SQLSetCursorName(hstmtS, "C1", SQL_NTS);  
SQLExecDirect(hstmtS, "SELECT ORDERID, STATUS FROM ORDERS ", SQL_NTS);  
  
SQLBindCol(hstmtS, 1, SQL_C_ULONG, &sOrderID, 0, &cbOrderID);  
SQLBindCol(hstmtS, 2, SQL_C_CHAR, szStatus, STATUS_LEN, &cbStatus);  
  
while ((retcode == SQLFetchScroll(hstmtS, SQL_FETCH_NEXT, 0)) != SQL_ERROR) {  
   if (retcode == SQL_NO_DATA_FOUND)  
      break;  
   for (irow = 0; irow < crow; irow++) {  
      if (rgfRowStatus[irow] != SQL_ROW_DELETED)  
         printf("%2d %5d %*s\n", irow+1, sOrderID, NAME_LEN-1, szStatus[irow]);  
   }  
   while (TRUE) {  
      printf("\nRow number to update?");  
      gets_s(szReply, 3);  
      irow = atoi(szReply);  
      if (irow > 0 && irow <= crow) {  
         printf("\nNew status?");  
         gets_s(szStatus[irow-1], (ROWS * STATUS_LEN));  
         SQLSetPos(hstmtS, irow, SQL_POSITION, SQL_LOCK_NO_CHANGE);  
         SQLPrepare(hstmtU,  
          "UPDATE ORDERS SET STATUS=? WHERE CURRENT OF C1", SQL_NTS);  
         SQLBindParameter(hstmtU, 1, SQL_PARAM_INPUT,  
            SQL_C_CHAR, SQL_CHAR,  
            STATUS_LEN, 0, szStatus[irow], 0, NULL);  
         SQLExecute(hstmtU);  
      } else if (irow == 0) {  
         break;  
      }  
   }  
}  

その他の例については、「位置指定された更新および削除ステートメント」および「SQLSetPos を使用した行セット内の行の更新」を参照してください。

対象 解決方法については、
結果セット内の列へのバッファーのバインド SQLBindCol 関数
ブロック カーソル位置に関連しない一括操作の実行 SQLBulkOperations 関数
ステートメント処理の取り消し SQLCancel 関数
データブロックのフェッチまたは結果セットのスクロール SQLFetchScroll 関数
記述子の 1 つのフィールドを取得する SQLGetDescField 関数
記述子の複数のフィールドを取得する SQLGetDescRec 関数
記述子の 1 つのフィールドの設定 SQLSetDescField 関数
記述子の複数のフィールドの設定 SQLSetDescRec 関数
ステートメント属性の設定 SQLSetStmtAttr 関数

参照

ODBC API リファレンス
ODBC ヘッダー ファイル