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をサポートする必要があります。 この機能は、SQL_ADDの操作を使用した SQLBulkOperations の呼び出しに置き換えられました。 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の HandleType と StatementHandle のハンドルを使用して 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の説明を参照してください。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 番目のフィールド) がフィールドの許容値の範囲外であるか、グレゴリオ暦の 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 に対して非同期処理が有効になりました。 関数が呼び出され、実行が完了する前に、StatementHandle で SQLCancel または SQLCancelHandle が呼び出され、その後、その関数が StatementHandle で再度呼び出されました。 関数が呼び出され、実行が完了する前に、SQLCancel または SQLCancelHandle がマルチスレッド アプリケーション内の別のスレッドから StatementHandle で呼び出されました。 |
HY010 | 関数シーケンス エラー | (DM) StatementHandle に関連付けられている接続ハンドルに対して非同期実行関数が呼び出されました。 この非同期関数は、SQLSetPos 関数が呼び出されたときにまだ実行されていました。 (DM) 指定された StatementHandle が実行された状態にありません。 この関数は、SQLExecDirect、SQLExecute、またはカタログ関数を最初に呼び出さずに呼び出されました。 (DM) 非同期実行関数 (この関数ではない) が StatementHandle に対して呼び出され、この関数が呼び出されたときにはまだ実行されていました。 (DM) StatementHandle に対して SQLExecute、SQLExecDirect、SQLBulkOperations、または SQLSetPos が呼び出され、SQL_NEED_DATA返されました。 この関数は、すべての実行時データ パラメーターまたは列に対してデータが送信される前に呼び出されました。 (DM) ドライバーは ODBC 2.x ドライバーであり、SQLSetPos は SQLFetch が呼び出された後に StatementHandle に対して呼び出されました。 |
HY011 | 現在、属性を設定できません | (DM) ドライバーは ODBC 2.x ドライバーでした。SQL_ATTR_ROW_STATUS_PTR ステートメント属性が設定されました。SQLSetPos は、SQLFetch、SQLFetchScroll、または 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 を呼び出す必要があります。 |
Comments
注意事項
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 の呼び出し。
たとえば、SQL_DELETEの操作を使用した 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 の行方向と列方向のバインドの説明を参照してください。 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 で指定された行にカーソルを置き、行セット バッファーの値 (SQLBindCol の TargetValuePtr 引数) を使用して、基になるデータ行を更新します。 長さ/インジケーター バッファー (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 が 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 つのステートメントによって取得されるロックは、同じ接続上の別のステートメントによってロック解除できます。
LOCKType が SQL_LOCK_UNLOCK に設定された行に対してアプリケーションが SQLSetPos を呼び出すまで、またはアプリケーションがステートメントに対して SQLFreeHandle を呼び出すまで、または SQL_CLOSE オプションを指定して SQLFreeStmt を呼び出すまで、SQLSetPos によってロックされた行はロックされたままになります。 トランザクションをサポートするドライバーの場合、アプリケーションが 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、SQLFetchScroll、SQLBulkOperations、または 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 を呼び出す前に、次の一連の手順を実行する必要があります。
アプリケーションで操作が SQL_UPDATE に設定された SQLSetPos を呼び出す場合は、各列の SQLBindCol (または SQLSetDescRec) を呼び出して、そのデータ型を指定し、列のデータと長さのバッファーをバインドします。
アプリケーションで操作が SQL_DELETE または SQL_UPDATE に設定された SQLSetPos を呼び出す場合は、SQLColAttribute を呼び出して、削除または更新する列が更新可能であることを確認します。
SQLExecDirect、SQLExecute、またはカタログ関数を呼び出して、結果セットを作成します。
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 を使用してデータを更新するには、次の手順を実行します。
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" を返す場合、長さはパラメーターに送信されるデータのバイト数です。それ以外の場合は、負以外の値である必要があり、無視されます。
データ行を更新するために、Operation 引数を SQL_UPDATE に設定して SQLSetPos を呼び出します。
実行時データ列がない場合、プロセスは完了です。
実行中のデータ列がある場合、関数はSQL_NEED_DATAを返し、手順 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 バッファー内の行のアドレスです。
SQLPutData を 1 回以上呼び出して、列のデータを送信します。 SQLPutData で指定された *TargetValuePtr バッファーですべてのデータ値を返すことができない場合は、複数の呼び出しが必要です。同じ列に対する SQLPutData への複数の呼び出しは、文字、バイナリ、またはデータ ソース固有のデータ型を持つ列に文字 C データを送信する場合、または文字を持つ列にバイナリ C データを送信する場合にのみ許可されます。 バイナリまたはデータ ソース固有のデータ型。
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を返し、すべての実行時列に対してデータが送信される前に、アプリケーションはステートメントまたはステートメントに関連付けられている接続に対して SQLCancel、SQLGetDiagField、SQLGetDiagRec、SQLGetFunctions、SQLParamData、または 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 つ以上の行を無視するようにドライバーに指示するには、アプリケーションで次の手順を実行する必要があります。
SQLSetStmtAttr を呼び出して、SQLUSMALLINT の配列を指すSQL_ATTR_ROW_OPERATION_PTRステートメント属性を設定します。 このフィールドは、SQLSetDescField を呼び出して ARD の SQL_DESC_ARRAY_STATUS_PTR ヘッダー フィールドを設定することによっても設定できます。そのためには、アプリケーションが記述子ハンドルを取得する必要があります。
行操作配列の各要素を、次の 2 つの値のいずれかに設定します。
SQL_ROW_IGNORE、一括操作で行が除外されることを示します。
SQL_ROW_PROCEED、行が一括操作に含まれていることを示します。 (これは既定値です)。
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 が呼び出された場合、SQLSetPos の呼び出し後、行セット内の n 番目の行は変更されません。
アプリケーションは、読み取り専用列を自動的に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 関数 |
記述子の単一フィールドの設定 | SQLSetDescField 関数 |
記述子の複数のフィールドの設定 | SQLSetDescRec 関数 |
ステートメント属性の設定 | SQLSetStmtAttr 関数 |