次の方法で共有


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

ODBC 3.x では、Operation 引数のSQL_ADD値は非推奨になりました。 ODBC 3.x ドライバーは、下位互換性のためにSQL_ADDをサポートする必要があります。 この機能は、 SQLBulkOperations の呼び出しに置き換えられました Operation SQL_ADD。 ODBC 3.x アプリケーションが ODBC 2.x ドライバーで動作する場合、ドライバー マネージャーは、 SQLBulkOperations Operation SQL_ADD の呼び出しを SQLSetPos Operation 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のHandleType を使用してSQLGetDiagRecを呼び出すことによって取得できます。 次の表に、 SQLSetPos によって一般的に返される SQLSTATE 値を示し、この関数のコンテキストでそれぞれについて説明します。表記 "(DM)" は、ドライバー マネージャーによって返される SQLSTATE の説明の前にあります。 特に明記されていない限り、各 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であり、行または複数の行が削除または更新されませんでした。 (複数行の更新の詳細については、SQL_ATTR_SIMULATE_CURSOR の説明を参照してください。attribute SQLSetStmtAttr.) (関数は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 は、SQLSetPos は、ドライバーが ODBC 2.x ドライバーであり、カーソル ライブラリが使用されていない場合は、SQLExtendedFetch の後に呼び出されます。
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 間隔フィールドのオーバーフロー 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 に対して非同期処理が有効になりました。 関数が呼び出され、実行が完了する前に、 SQLCancel または SQLCancelHandleStatementHandle で呼び出され、 StatementHandle で関数が再度呼び出されました。

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

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

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

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

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

Comments

注意事項

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

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 を呼び出します。

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

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

Operation 引数

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

操作

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

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

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

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

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

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_REFRESH Operation では、SQL_ATTR_ROW_OPERATION_PTR ステートメント属性が指す行状態配列の内容は無視されます。
SQL_UPDATE ドライバーは、RowNumber で指定された行にカーソルを置き、基になるデータ行を行セット バッファーの値 (SQLBindColTargetValuePtr 引数) で更新します。 データの長さ/インジケーター バッファー (SQLBindCol のStrLen_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 を使用した SQLSetPos の呼び出しSQL_POSITION以外の何も設定されていません。 パッキングをサポートするドライバーの場合、データ ソースから新しいデータを取得すると、行がカーソルから削除されます。

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

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

LockType 引数

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

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

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

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

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

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 フィールドが指すように) には、行セット内のデータの各行の状態値が含まれます。 ドライバーは、 SQLFetchSQLFetchScrollSQLBulkOperations、または 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. OperationをSQL_UPDATEに設定してSQLSetPosを呼び出す場合は各列のSQLBindCol (または SQLSetDescRec) を呼び出して、そのデータ型を指定し、列のデータと長さのバッファーをバインドします。

  2. アプリケーションが Operation 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 でデータが渡される列は、data-at-execution columns と呼ばれます。 これらは通常、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

    実行時データ パラメーターは SQL ステートメントのパラメーターであり、ステートメントが SQLExecDirect または SQLExecute で実行されるときに、SQLPutData でデータが送信されます。 これらは、 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を返します。 この時点で、 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ではありません。 sqlSetPos Operation SQL_POSITIONで、 RowNumber が 0 の場合、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のOperationSQLSetPosを使用した一括操作にのみ影響します。 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;  
      }  
   }  
}  

その他の例については、「 Positioned Update ステートメントと Delete ステートメント sqlSetPos を使用した行セット内の行の追加を参照してください。

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

参照

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