次の方法で共有


SQLCopyDesc 関数

準拠
導入されたバージョン: ODBC 3.0 標準コンプライアンス: ISO 92

まとめ
SQLCopyDesc は、記述子ハンドルから別の記述子ハンドルに記述子情報をコピーします。

構文

  
SQLRETURN SQLCopyDesc(  
     SQLHDESC     SourceDescHandle,  
     SQLHDESC     TargetDescHandle);  

引数

SourceDescHandle
[入力]ソース記述子ハンドル。

TargetDescHandle
[入力]ターゲット記述子ハンドル。 TargetDescHandle引数には、アプリケーション記述子または IPD へのハンドルを指定できます。 TargetDescHandleを IRD へのハンドルに設定することはできません。または、SQLCopyDesc は SQLSTATE HY016 を返します (実装行記述子を変更できません)。

返品

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_ERROR、またはSQL_INVALID_HANDLE。

診断

SQLCopyDescがSQL_ERRORまたはSQL_SUCCESS_WITH_INFOを返す場合は、SQL_HANDLE_DESCのHandleTypeTargetDescHandleHandleSQLGetDiagRecを呼び出すことによって、関連付けられた SQLSTATE 値を取得できます。 呼び出しで無効な SourceDescHandle が渡された場合、SQL_INVALID_HANDLEは返されますが、SQLSTATE は返されません。 次の表は、 SQLCopyDesc によって一般的に返される SQLSTATE 値を示し、この関数のコンテキストでそれぞれについて説明します。表記 "(DM)" は、ドライバー マネージャーによって返される SQLSTATEs の説明の前にあります。 特に明記されていない限り、各 SQLSTATE 値に関連付けられている戻りコードはSQL_ERROR。

エラーが返されると、 SQLCopyDesc の呼び出しはすぐに中止され、 TargetDescHandle 記述子内のフィールドの内容は未定義になります。

SQLCopyDescは、SQLGetDescFieldおよびSQLSetDescFieldを呼び出すことによって実装できるため、SQLCopyDesc は、SQLGetDescField または SQLSetDescField によって返される SQLSTATEs を返す場合があります。

SQLSTATE エラー 説明
01000 一般的な警告 ドライバー固有の情報メッセージ。 (関数はSQL_SUCCESS_WITH_INFOを返します。
08S01 通信リンクエラー ドライバーとドライバーが接続されたデータ ソース間の通信リンクは、関数の処理が完了する前に失敗しました。
HY000 一般的なエラー 特定の SQLSTATE がなく、実装固有の SQLSTATE が定義されていないエラーが発生しました。 *MessageText バッファー内の SQLGetDiagRec によって返されるエラー メッセージには、エラーとその原因が記述されています。
HY001 メモリ割り当てエラー ドライバーは、関数の実行または完了をサポートするために必要なメモリを割り当てませんでした。
HY007 関連付けられたステートメントが準備されていません SourceDescHandle は IRD に関連付けられていたが、関連付けられたステートメント ハンドルが準備済みまたは実行済みの状態ではなかった。
HY010 関数シーケンス エラー (DM) SourceDescHandle または TargetDescHandle の記述子ハンドルは、非同期実行関数 (この関数ではなく) が呼び出され、この関数が呼び出されたときにまだ実行されていたStatementHandle に関連付けられていた。

(DM) SourceDescHandle または TargetDescHandle 内の記述子ハンドルが、SQLExecuteStatementHandleに関連付けられていた。 SQLExecDirectSQLBulkOperations、または SQLSetPos が呼び出され、SQL_NEED_DATA返されました。 この関数は、すべての実行時データ パラメーターまたは列に対してデータが送信される前に呼び出されました。

(DM) 非同期実行関数が、 SourceDescHandle または TargetDescHandle に関連付けられている接続ハンドルに対して呼び出されました。 この非同期関数は、 SQLCopyDesc 関数が呼び出されたときにまだ実行されていました。

(DM) SQLExecuteSQLExecDirect、または SQLMoreResults SourceDescHandle または TargetDescHandle に関連付けられているステートメント ハンドルの 1 つに対して呼び出され、SQL_PARAM_DATA_AVAILABLEが返されました。 この関数は、すべてのストリーミング パラメーターのデータが取得される前に呼び出されました。
HY013 メモリ管理エラー メモリが不足している可能性があるため、基になるメモリ オブジェクトにアクセスできなかったため、関数呼び出しを処理できませんでした。
HY016 実装行記述子を変更できません TargetDescHandle は IRD に関連付けられていた。
HY021 一貫性のない記述子情報 整合性チェック中にチェックされた記述子情報に一貫性がありません。 詳細については、 SQLSetDescField の「整合性チェック」を参照してください。
HY092 無効な属性/オプション識別子 SQLCopyDesc を呼び出すと、SQLSetDescField の呼び出しが求められたが、*ValuePtr TargetDescHandleFieldIdentifier 引数に対しては無効でした。
HY117 不明なトランザクション状態のため、接続が中断されます。 切断関数と読み取り専用関数のみが許可されます。 (DM) 中断状態の詳細については、「 SQLEndTran 関数を参照してください。
HYT01 接続のタイムアウト データ ソースが要求に応答する前に、接続タイムアウト期間の有効期限が切れています。 接続タイムアウト期間は、SQL_ATTR_CONNECTION_TIMEOUT SQLSetConnectAttr によって設定されます。
IM001 ドライバーは、この関数をサポートしていません (DM) SourceDescHandle または TargetDescHandle に関連付けられているドライバーは、関数をサポートしていません。

Comments

SQLCopyDesc を呼び出すと、ソース記述子ハンドルのフィールドがターゲット記述子ハンドルにコピーされます。 フィールドは、アプリケーション記述子または IPD にのみコピーでき、IRD にはコピーできません。 フィールドは、アプリケーションまたは実装記述子からコピーできます。

IRD からフィールドをコピーできるのは、ステートメント ハンドルが準備済みまたは実行済み状態の場合のみです。それ以外の場合、関数は SQLSTATE HY007 を返します (Associated ステートメントは準備されていません)。

ステートメントが準備されているかどうかに関係なく、IPD からフィールドをコピーできます。 動的パラメーターを持つ SQL ステートメントが準備されていて、IPD の自動作成がサポートされ、有効になっている場合は、ドライバーによって IPD が設定されます。 SQLCopyDescが IPD をSourceDescHandleとして呼び出されると、設定されたフィールドがコピーされます。 ドライバーによって IPD が設定されていない場合は、最初に IPD 内のフィールドの内容がコピーされます。

記述子のすべてのフィールド (記述子ハンドルが自動的に割り当てられたか明示的に割り当てられたかを指定する) SQL_DESC_ALLOC_TYPEを除き、フィールドが宛先記述子に対して定義されているかどうかに関係なく、コピーされます。 コピーされたフィールドは、既存のフィールドを上書きします。

ドライバーが 2 つの異なる接続または環境にある場合でも、 SourceDescHandle および TargetDescHandle 引数が同じドライバーに関連付けられている場合、ドライバーはすべての記述子フィールドをコピーします。 SourceDescHandleおよび TargetDescHandle 引数が異なるドライバーに関連付けられている場合、ドライバー マネージャーは ODBC で定義されたフィールドをコピーしますが、記述子の種類に対して ODBC で定義されていないドライバー定義のフィールドはコピーしません。

エラーが発生した場合、 SQLCopyDesc の呼び出しは直ちに中止されます。

SQL_DESC_DATA_PTR フィールドがコピーされると、ターゲット記述子に対して整合性チェックが実行されます。 整合性チェックが失敗すると、SQLSTATE HY021 (不整合な記述子情報) が返され、 SQLCopyDesc の呼び出しが直ちに中止されます。 整合性チェックの詳細については、 SQLSetDescRec 関数の「整合性チェック」を参照してください。

記述子ハンドルは、接続が異なる環境にある場合でも、接続間でコピーできます。 ドライバー マネージャーは、ソースと宛先の記述子ハンドルが同じ接続に属していないと検出し、2 つの接続が個別のドライバーに属している場合は、SQLGetDescFieldSQLSetDescField を使用してフィールドごとのコピーを実行することで、SQLCopyDesc を実装します。

SQLCopyDescが 1 つのドライバーで SourceDescHandle と別のドライバーの TargetDescHandle で呼び出されると、SourceDescHandle のエラー キューがクリアされます。 これは、この場合 SQLCopyDesc が、 SQLGetDescField および SQLSetDescField の呼び出しによって実装されるために発生します。

Note

アプリケーションでは、SQLCopyDesc を呼び出して記述子間でフィールドをコピーするのではなく、明示的に割り当てられた記述子ハンドルを StatementHandle に関連付けることができます。 明示的に割り当てられた記述子は、明示的に割り当てられた記述子のハンドルにSQL_ATTR_APP_ROW_DESCまたはSQL_ATTR_APP_PARAM_DESCステートメント属性を設定することで同じConnectionHandleの別のStatementHandle に関連付けることができます。 これが行われると、記述子フィールド値を記述子から別の記述子にコピーするために、 SQLCopyDesc を呼び出す必要はありません。 ただし、別の ConnectionHandleStatementHandleに記述子ハンドルを関連付けることはできません。StatementHandles で同じ記述子フィールド値を使用するには異なる ConnectionHandlesSQLCopyDesc を呼び出す必要があります。

記述子ヘッダーまたはレコード内のフィールドの説明については、「 SQLSetDescField 関数を参照してください。 記述子の詳細については、「 Descriptors」を参照してください。

テーブル間での行のコピー

アプリケーションは、アプリケーション レベルでデータをコピーすることなく、あるテーブルから別のテーブルにデータをコピーできます。 これを行うために、アプリケーションは、データをフェッチするステートメントと、データをコピーに挿入するステートメントに、同じデータ バッファーと記述子情報をバインドします。 これは、アプリケーション記述子を共有するか (明示的に割り当てられた記述子を ARD ステートメントと APD の両方として別のステートメントにバインドする)、または SQLCopyDesc を使用して 2 つのステートメントの ARD と APD の間でバインディングをコピーすることによって実現できます。 ステートメントが異なる接続にある場合は、 SQLCopyDesc を使用する必要があります。 さらに、SQLCopyDesc を呼び出して、2 つのステートメントの IRD と IPD の間のバインディングをコピーする必要があります。 同じ接続上のステートメント間でコピーする場合、 SQLGetInfo の呼び出しに対してドライバーによって返されるSQL_ACTIVE_STATEMENTS情報の種類 この操作が成功するには 1 より大きい必要があります。 (これは、複数の接続をコピーする場合には当たりません)。

コード例

次の例では、記述子操作を使用して PartsSource テーブルのフィールドを PartsCopy テーブルにコピーします。 PartsSource テーブルの内容は、 hstmt0 の行セット バッファーにフェッチされます。 これらの値は、partsCopy テーブルの列を設定するために、 hstmt1 の INSERT ステートメントのパラメーターとして使用されます。 これを行うには、 hstmt0 の IRD のフィールドが hstmt1 の IPD のフィールドにコピーされ、 hstmt0 の ARD のフィールドが hstmt1 の APD のフィールドにコピーされます。 SQLSetDescField を使用して、出力パラメーターを含むステートメントから入力パラメーターである必要がある IPD フィールドに IRD フィールドをコピーするときに、IPD のSQL_DESC_PARAMETER_TYPE属性をSQL_PARAM_INPUTに設定します。

#define ROWS 100  
#define DESC_LEN 50  
#define SQL_SUCCEEDED(rc) (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)  
  
// Template for a row  
typedef struct {  
   SQLINTEGER   sPartID;  
   SQLINTEGER   cbPartID;  
   SQLUCHAR     szDescription[DESC_LENGTH];  
   SQLINTEGER   cbDescription;  
   REAL         sPrice;  
   SQLINTEGER   cbPrice;  
} PartsSource;  
  
PartsSource    rget[ROWS];          // rowset buffer  
SQLUSMALLINT   sts_ptr[ROWS];       // status pointer  
SQLHSTMT       hstmt0, hstmt1;  
SQLHDESC       hArd0, hIrd0, hApd1, hIpd1;  
  
// ARD and IRD of hstmt0  
SQLGetStmtAttr(hstmt0, SQL_ATTR_APP_ROW_DESC, &hArd0, 0, NULL);  
SQLGetStmtAttr(hstmt0, SQL_ATTR_IMP_ROW_DESC, &hIrd0, 0, NULL);  
  
// APD and IPD of hstmt1  
SQLGetStmtAttr(hstmt1, SQL_ATTR_APP_PARAM_DESC, &hApd1, 0, NULL);  
SQLGetStmtAttr(hstmt1, SQL_ATTR_IMP_PARAM_DESC, &hIpd1, 0, NULL);  
  
// Use row-wise binding on hstmt0 to fetch rows  
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER) sizeof(PartsSource), 0);  
  
// Set rowset size for hstmt0  
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);  
  
// Execute a select statement  
SQLExecDirect(hstmt0, "SELECT PARTID, DESCRIPTION, PRICE FROM PARTS ORDER BY 3, 1, 2"",  
               SQL_NTS);  
  
// Bind  
SQLBindCol(hstmt0, 1, SQL_C_SLONG, rget[0].sPartID, 0,   
   &rget[0].cbPartID);  
SQLBindCol(hstmt0, 2, SQL_C_CHAR, &rget[0].szDescription, DESC_LEN,   
   &rget[0].cbDescription);  
SQLBindCol(hstmt0, 3, SQL_C_FLOAT, rget[0].sPrice,   
   0, &rget[0].cbPrice);  
  
// Perform parameter bindings on hstmt1.   
SQLCopyDesc(hArd0, hApd1);  
SQLCopyDesc(hIrd0, hIpd1);  
  
// Set the array status pointer of IRD  
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_STATUS_PTR, sts_ptr, SQL_IS_POINTER);  
  
// Set the ARRAY_STATUS_PTR field of APD to be the same  
// as that in IRD.  
SQLSetStmtAttr(hstmt1, SQL_ATTR_PARAM_OPERATION_PTR, sts_ptr, SQL_IS_POINTER);  
  
// Set the hIpd1 records as input parameters  
rc = SQLSetDescField(hIpd1, 1, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);  
rc = SQLSetDescField(hIpd1, 2, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);  
rc = SQLSetDescField(hIpd1, 3, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);  
  
// Prepare an insert statement on hstmt1. PartsCopy is a copy of  
// PartsSource  
SQLPrepare(hstmt1, "INSERT INTO PARTS_COPY VALUES (?, ?, ?)", SQL_NTS);  
  
// In a loop, fetch a rowset, and copy the fetched rowset to PARTS_COPY  
  
rc = SQLFetchScroll(hstmt0, SQL_FETCH_NEXT, 0);  
while (SQL_SUCCEEDED(rc)) {  
  
   // After the call to SQLFetchScroll, the status array has row   
   // statuses. This array is used as input status in the APD  
   // and hence determines which elements of the rowset buffer  
   // are inserted.  
   SQLExecute(hstmt1);  
  
   rc = SQLFetchScroll(hstmt0, SQL_FETCH_NEXT, 0);  
} // while  
情報 参照トピック
複数の記述子フィールドの取得 SQLGetDescRec 関数
単一記述子フィールドの設定 SQLSetDescField 関数
複数の記述子フィールドの設定 SQLSetDescRec 関数

参照

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