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

Note

Operation 引数のSQL_ADD値は、ODBC 3.x では非推奨となりました。 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の HandleTypeStatementHandleHandle を指定して SQLGetDiagRec を呼び出します。 次の表に、 SQLSetPos によって一般的に返される SQLSTATE 値の一覧を示し、この関数のコンテキストでそれぞれについて説明します。表記 "(DM)" は、ドライバー マネージャーによって返される SQLSTATEs の説明の前にあります。 特に明記されていない限り、各 SQLSTATE 値に関連付けられている戻りコードはSQL_ERRORされます。

SQL_SUCCESS_WITH_INFOまたはSQL_ERRORを返すことができるすべての SQLSTATEs (01xxx 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が返されます)。

(ドライバーが ODBC 2.x ドライバーであり、カーソル ライブラリが使用されていない場合、SQLExtendedFetch の後に SQLSetPos が呼び出された場合にのみ、この SQLSTATE が返されます)。
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 番目のフィールド) がフィールドの値の許容範囲外であるか、グレゴリオ暦の datetime の自然なルールに基づいて無効になります。

Operation 引数がSQL_REFRESHされ、結果セットから取得されたデータに対する datetime 算術のパフォーマンスにより、結果の datetime フィールド (年、月、日、時間、分、または 2 番目のフィールド) がフィールドの許容範囲外であるか、グレゴリオ暦の datetime の自然なルールに基づいて無効になります。
22015 間隔フィールドのオーバーフロー 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され、更新は表示テーブルまたは WITH CHECK OPTION を指定して作成された表示テーブルから派生したテーブルに対して実行され、更新の影響を受ける 1 つ以上の行が表示テーブルに存在しなくなります。
HY000 一般的なエラー 特定の SQLSTATE がなく、実装固有の SQLSTATE が定義されていないエラーが発生しました。 *MessageText バッファー内の SQLGetDiagRec によって返されるエラー メッセージは、エラーとその原因を説明します。
HY001 メモリ割り当てエラー ドライバーは、関数の実行または完了をサポートするために必要なメモリを割り当てることができませんでした。
HY008 操作が取り消されました StatementHandle に対して非同期処理が有効になりました。 関数が呼び出され、実行が完了する前に、StatementHandleSQLCancel または SQLCancelHandle が呼び出され、その関数が StatementHandle で再度呼び出されました。

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

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

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

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

(DM) ドライバーは ODBC 2.x ドライバーであり、SQLFetch が呼び出された後に SQLSetPosStatementHandle に対して呼び出されました。
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 接続のタイムアウト データ ソースが要求に応答する前に、接続タイムアウト期間の有効期限が切れています。 接続タイムアウト期間は、 SQLSetConnectAttr (SQL_ATTR_CONNECTION_TIMEOUT) によって設定されます。
IM001 ドライバーは、この関数をサポートしていません (DM) StatementHandle に関連付けられているドライバーは、 関数をサポートしていません。
IM017 非同期通知モードでポーリングが無効になっている 通知モデルが使用されるたびに、ポーリングは無効になります。
IM018 SQLCompleteAsync は、このハンドルで前の非同期操作を完了するために呼び出されていません。 ハンドルの前の関数呼び出しがSQL_STILL_EXECUTINGを返し、通知モードが有効になっている場合は、処理後に処理を実行して操作を完了するために、 SQLCompleteAsync をハンドルで呼び出す必要があります。

説明

注意事項

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

RowNumber 引数

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

Note

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

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

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

  • SQLGetData を呼び出します。

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

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

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

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

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

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

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 を呼び出すか、 sqlFreeStmt を SQL_CLOSE オプションと共に呼び出すまで、ロックされた行はロックされたままになります。 ドライバーがトランザクションをサポートし、トランザクションのコミットまたはロールバック時にカーソルを閉じると、アプリケーションは SQLEndTran を呼び出します。

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

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

  • アプリケーションが 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_DESC_ARRAY_STATUS_PTR フィールドと SQL_ATTR_ROW_STATUS_ARRAY ステートメント属性が指す) には、行セット内のデータ行ごとに状態値が含まれます。 ドライバーは、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. アプリケーションが SQLSetPos を呼び出し、 Operation を SQL_UPDATE に設定した場合は、各列の SQLBindCol (または SQLSetDescRec) を呼び出して、そのデータ型を指定し、列のデータと長さのバッファーをバインドします。

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

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

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

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

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

SQLSetPos を使用してデータを削除するために、アプリケーションは SQLSetPos を呼び出し、RowNumber を削除する行の番号に設定し、Operation を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. 引数 Operation を SQL_UPDATE に設定して SQLSetPos を呼び出して、データ行を更新します。

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

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

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

    Note

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

    Note

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

    Note

    実行時のデータ列は、行が 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を返します。 この時点で、 SQLParamDataSQLSetPos によって返すことができる任意の SQLSTATE を返すことができます。

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

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

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

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

一括操作の実行

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 の Operation を使用した 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;  
      }  
   }  
}  

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

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

参照

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