共用方式為


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的 HandleType 和 TargetDescHandleHandleType 呼叫 SQLGetDiagRec 來取得相關聯的 SQLSTATE 值。 如果在呼叫中傳遞了無效 的SourceDescHandle ,則會傳回SQL_INVALID_HANDLE,但不會傳回任何SQLSTATE。 下表列出 SQLCopyDesc 通常傳回的 SQLSTATE 值,並說明此函式內容中的每個值;表示法 “(DM)” 在驅動程式管理員傳回的 SQLSTATE 描述之前。 除非另有說明,否則與每個 SQLSTATE 值相關聯的傳回碼會SQL_ERROR。

傳回錯誤時,會立即中止對 SQLCopyDesc 的呼叫,且 TargetDescHandle 描述元中字段的內容未定義。

因為 SQLCopyDesc 可藉由呼叫 SQLGetDescField 和 SQLSetDescField 來實作,SQLCopyDescc 可能會傳回 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 中的描述元句柄與 SQLExecute、SQLExecDirectSQLBulkOperationsSQLSetPos 呼叫並傳回SQL_NEED_DATA的 StatementHandle 相關聯。 在針對所有數據執行中參數或數據行傳送數據之前,會呼叫此函式。

(DM) 針對與 SourceDescHandle 或 TargetDescHandle 相關聯的連接句柄呼叫異步執行函式。 呼叫 SQLCopyDesc 函式時,這個異步函式仍在執行中。

(DM) 已針對與 SourceDescHandle 或 TargetDescHandle 相關聯的其中一個語句句柄呼叫 SQLExecuteSQLExecDirectSQLMoreResults,並傳回SQL_PARAM_DATA_AVAILABLE。 在擷取所有數據流參數的數據之前,會呼叫此函式。
HY013 記憶體管理錯誤 無法處理函式呼叫,因為基礎記憶體物件無法存取,可能是因為記憶體不足的情況。
HY016 無法修改實作數據列描述元 TargetDescHandle 與 IRD 相關聯。
HY021 不一致的描述元資訊 在一致性檢查期間檢查的描述元資訊不一致。 如需詳細資訊,請參閱 SQLSetDescField 中的
HY092 無效的屬性/選項識別碼 對 SQLCopyDesc 的呼叫會提示呼叫 SQLSetDescField,但 *ValuePtrTargetDescHandle 上的 FieldIdentifier 自變數無效。
HY117 聯機因為未知的交易狀態而暫停。 只允許中斷連線和唯讀函式。 (DM) 如需暫停狀態的詳細資訊,請參閱 SQLEndTran 函式
HYT01 已超過連線逾時 在數據源回應要求之前,連線逾時期限已過期。 線上逾時期間是透過 SQLSetConnectAttr 來設定,SQL_ATTR_CONNECTION_TIMEOUT。
IM001 驅動程式不支援此函式 (DM) 與 SourceDescHandle 或 TargetDescHandle 相關聯的驅動程式不支援 函式。

註解

對 SQLCopyDesc呼叫會將來源描述元句柄的欄位複製到目標描述元句柄。 欄位只能複製到應用程式描述項或 IPD,但不能複製到 IRD。 欄位可以從應用程式或實作描述元複製。

只有當語句句柄處於備妥或執行狀態時,才能從 IRD 複製字段;否則,函式會傳回 SQLSTATE HY007(未準備相關語句)。

不論是否已備妥語句,都可以從IPD複製欄位。 如果已備妥具有動態參數的 SQL 語句,並啟用 IPD 的自動母體擴展,則驅動程式會填入 IPD。 當使用IPD呼叫SQLCopyDesc做為SourceDescHandle,會複製填入的欄位。 如果驅動程式未填入IPD,則會複製原本在IPD中的欄位內容。

除了SQL_DESC_ALLOC_TYPE以外的所有描述項欄位(指定描述項句柄是否自動或明確配置),都會複製,無論字段是否為目的地描述元定義。 複製的欄位會覆寫現有欄位。

如果 SourceDescHandle 和 TargetDescHandle 自變數與相同的驅動程式相關聯,即使驅動程式位於兩個不同的連接或環境上,驅動程式也會複製所有描述元字段。 如果 SourceDescHandle 和 TargetDescHandle 自變數與不同的驅動程式相關聯,驅動程式管理員會複製 ODBC 定義的欄位,但不會複製 ODBC 為描述元類型未定義的驅動程式定義欄位或欄位。

如果發生錯誤,就會立即中止對 SQLCopyDesc 的呼叫

複製SQL_DESC_DATA_PTR欄位時,會在目標描述元上執行一致性檢查。 如果一致性檢查失敗,則會傳回 SQLSTATE HY021 (不一致的描述元資訊),並立即中止對 SQLCopyDesc呼叫。 如需一致性檢查的詳細資訊,請參閱 SQLSetDescRec 函式中的

即使連接位於不同的環境中,也可以跨連線複製描述項句柄。 如果驅動程式管理員偵測到來源和目的地描述元句柄不屬於相同的連接,而且兩個連接屬於不同的驅動程式,它會使用 SQLGetDescField 和 SQLSetDescField 執行欄位逐字段複製來實作 SQLCopyDescc

SQLCopyDesc 在一個驅動程式上使用 SourceDescHandle 呼叫,在另一個驅動程式上呼叫 TargetDescHandle 時,就會清除 SourceDescHandle 的錯誤佇列這是因為此案例中的 SQLCopyDesc 是由 SQLGetDescField 和 SQLSetDescField呼叫實作。

注意

應用程式可能會將明確配置的描述元句柄與 StatementHandle 產生關聯,而不是呼叫 SQLCopyDesc,將字段從一個描述元複製到另一個描述元。 明確配置的描述元可以藉由將SQL_ATTR_APP_ROW_DESC或SQL_ATTR_APP_PARAM_DESC語句屬性設定為明確配置的描述元句柄,來與相同 ConnectionHandle 上的另一個 StatementHandle 產生關聯。 完成此作業時, 不需要呼叫 SQLCopyDesc ,即可將描述元域值從一個描述元複製到另一個描述元。 但是,描述元句柄無法與另一個 ConnectionHandle 上的 StatementHandle 相關聯;若要在不同的 ConnectionHandles 上使用語句Handles 上的相同描述元域值,必須呼叫 SQLCopyDesc

如需描述元標頭或記錄中字段的描述,請參閱 SQLSetDescField 函式。 如需描述項的詳細資訊,請參閱 描述項

在數據表之間複製數據列

應用程式可能會將數據從某個數據表複製到另一個數據表,而不需在應用層級複製數據。 若要這樣做,應用程式會將相同的數據緩衝區和描述項資訊系結至擷取數據的語句,以及將數據插入複本的語句。 這可以藉由共用應用程式描述元(將明確配置的描述元系結為ARD到另一個語句和另一個語句中的APD),或使用 SQLCopyDesc 複製兩個語句的ARD與APD之間的系結來完成。 如果語句位於不同的連接上, 則必須使用 SQLCopyDesc 。 此外, 必須呼叫 SQLCopyDesc ,才能複製兩個語句的 IRD 與 IPD 之間的系結。 在相同連接上跨語句複製時,驅動程式針對 SQLGetInfo 呼叫所傳回的SQL_ACTIVE_STATEMENTS資訊類型必須大於 1,此作業才能成功。 (跨連線複製時,情況並非如此。

程式碼範例

在下列範例中,描述項作業可用來將 PartsSource 數據表的欄位複製到 PartsCopy 資料表。 PartsSource 數據表的內容會擷取到 hstmt0 中的數據列集緩衝區中。 這些值會當做 hstmt1INSERT 語句的參數使用,以填入 PartsCopy 數據表的數據行。 若要這樣做,hstmt0 IRD 的欄位會複製到 hstmt1 的 IPD 欄位,並將 hstmt0 的 ARD 字段複製到 hstmt1APD 字段。 當您將具有輸出參數的 IRD 欄位複製到需要輸入參數的 IPD 欄位時,使用 SQLSetDDescField 將 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 標頭檔