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 和 TargetDescHandle HandleType 呼叫 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 、SQLExecDirect SQLBulkOperations SQLSetPos 呼叫並傳回SQL_NEED_DATA的 StatementHandle 相關聯。 在針對所有資料執行中參數或資料行傳送資料之前,會呼叫此函式。

(DM) 針對與 SourceDescHandle 或 TargetDescHandle 相關聯的連接控制碼呼叫非同步執行函 式。 呼叫 SQLCopyDesc 函式時 ,這個非同步函式仍在執行中。

(DM) 已針對與 SourceDescHandle 或 TargetDescHandle 相關聯的 其中一個語句控制碼呼叫 SQLExecute SQLExecDirect SQLMoreResults ,並傳回SQL_PARAM_DATA_AVAILABLE。 在擷取所有資料流程參數的資料之前,會呼叫此函式。
HY013 記憶體管理錯誤 無法處理函式呼叫,因為基礎記憶體物件無法存取,可能是因為記憶體不足的情況。
HY016 無法修改實作資料列描述元 TargetDescHandle 與 IRD 相關聯。
HY021 不一致的描述元資訊 在一致性檢查期間檢查的描述元資訊不一致。 如需詳細資訊,請參閱 SQLSetDescField 中的
HY092 不正確屬性/選項識別碼 對 SQLCopyDesc 的呼叫 會提示呼叫 SQLSetDescField ,但 *ValuePtr TargetDescHandle 上的 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 中的資料 列集緩衝區中。 這些值會當做 hstmt1 INSERT 語句的參數使用,以填入 PartsCopy 資料表的資料行。 若要這樣做,hstmt0 IRD 的欄位會複製到 hstmt1 的 IPD 欄位,並將 hstmt0 的 ARD 欄位複製到 hstmt1 APD 欄位。 當您將具有輸出參數的 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 標頭檔