Поделиться через


Функция 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, связанное значение SQLSTATE можно получить путем вызова SQLGetDiagRec с помощью HandleType SQL_HANDLE_DESC и Handle of TargetDescHandle. Если в вызове был передан недопустимый sourceDescHandle , SQL_INVALID_HANDLE будет возвращен, но sqlSTATE не будет возвращен. В следующей таблице перечислены значения SQLSTATE, которые обычно возвращаются SQLCopyDesc и объясняются каждый из них в контексте этой функции. Нотация "(DM)" предшествует описаниям SQLSTATEs, возвращаемым диспетчером драйверов. Возвращаемый код, связанный с каждым значением SQLSTATE, SQL_ERROR, если не указано иное.

При возврате ошибки вызов SQLCopyDesc немедленно прерван, а содержимое полей в дескрипторе TargetDescHandle не определено.

Так как SQLCopyDesc может быть реализован путем вызова SQLGetDescField и SQLSetDescField, SQLCopyDesc может возвращать SQLSTATEs, возвращаемые SQLGetDescField или SQLSetDescField.

SQLSTATE Ошибка Описание
01000 Общее предупреждение Информационное сообщение для конкретного драйвера. (Функция возвращает SQL_SUCCESS_WITH_INFO.)
08S01 Сбой связи Связь между драйвером и источником данных, к которому был подключен драйвер, произошел сбой до завершения обработки функции.
HY000 Общая ошибка Произошла ошибка, для которой не было определенного SQLSTATE и для которого не было определено значение SQLSTATE для конкретной реализации. Сообщение об ошибке, возвращаемое SQLGetDiagRec в буфере *MessageText , описывает ошибку и ее причину.
HY001 Ошибка выделения памяти Драйверу не удалось выделить память, необходимую для поддержки выполнения или завершения функции.
HY007 Связанная инструкция не подготовлена SourceDescHandle связан с IRD, а связанный дескриптор инструкции не был в подготовленном или исполняемом состоянии.
HY010 Ошибка последовательности функций Дескриптор дескриптора в SourceDescHandle или TargetDescHandle был связан с оператором StatementHandle, для которого была вызвана асинхронная функция (не эта) и по-прежнему выполнялась при вызове этой функции.

Дескриптор дескриптора в SourceDescHandle или TargetDescHandle был связан с оператором StatementHandle, для которого sqlExecute, SQLExecDirect, SQLBulkOperations или SQLSetPos был вызван и возвращен SQL_NEED_DATA. Эта функция была вызвана до отправки данных для всех параметров выполнения или столбцов.

(DM) Асинхронно выполняющаяся функция была вызвана для дескриптора соединения, связанного с SourceDescHandle или TargetDescHandle. Эта асинхронная функция по-прежнему выполнялась при вызове функции SQLCopyDesc .

(DM) SQLExecute, SQLExecDirect или SQLMoreResults был вызван для одного из дескрипторов инструкций, связанных с SourceDescHandle или TargetDescHandle и возвращенных SQL_PARAM_DATA_AVAILABLE. Эта функция была вызвана до получения данных для всех потоковых параметров.
HY013 Ошибка управления памятью Не удалось обработать вызов функции, так как к базовым объектам памяти не удалось получить доступ, возможно, из-за низкой памяти.
HY016 Не удается изменить дескриптор строки реализации TargetDescHandle связан с IRD.
HY021 Несогласованные сведения о дескрипторе Сведения дескриптора, проверяемые во время проверки согласованности, не согласованы. Дополнительные сведения см. в разделе "Проверки согласованности" в SQLSetDescField.
HY092 Недопустимый идентификатор атрибута или параметра Вызов SQLCopyDesc запросил вызов SQLSetDescField, но *ValuePtr недействителен для аргумента FieldIdentifier в TargetDescHandle.
HY117 Подключение приостановлено из-за неизвестного состояния транзакции. Разрешены только функции отключения и только для чтения. (DM) Дополнительные сведения о приостановленном состоянии см. в статье SQLEndTran Function.
HYT01 Время ожидания для подключения истекло Срок ожидания подключения истек до того, как источник данных ответил на запрос. Период времени ожидания подключения задается через SQLSetConnectAttr SQL_ATTR_CONNECTION_TIMEOUT.
IM001 Драйвер не поддерживает эту функцию (DM) Драйвер, связанный с SourceDescHandle или TargetDescHandle, не поддерживает функцию.

Комментарии

Вызов SQLCopyDesc копирует поля исходного дескриптора в целевой дескриптор дескриптора. Поля можно копировать только в дескриптор приложения или IPD, но не в IRD. Поля можно скопировать из приложения или дескриптора реализации.

Поля можно скопировать из IRD, только если дескриптор инструкции находится в состоянии подготовки или выполнения; в противном случае функция возвращает SQLSTATE HY007 (связанная инструкция не подготовлена).

Поля можно скопировать из IPD независимо от того, была ли подготовлена инструкция. Если инструкция SQL с динамическими параметрами подготовлена, а автоматическое заполнение IPD поддерживается и включено, IPD заполняется драйвером. При вызове SQLCopyDesc с IPD в качестве SourceDescHandle копируются заполненные поля. Если IPD не заполняется драйвером, копируются содержимое полей, первоначально входящие в IPD.

Все поля дескриптора, кроме SQL_DESC_ALLOC_TYPE (который указывает, был ли дескриптор дескриптор автоматически или явно выделен), копируются независимо от того, определено ли поле для дескриптора назначения. Скопированные поля перезаписывают существующие поля.

Драйвер копирует все поля дескриптора, если аргументы SourceDescHandle и TargetDescHandle связаны с одним драйвером, даже если драйверы находятся в двух разных соединениях или средах. Если аргументы SourceDescHandle и TargetDescHandle связаны с различными драйверами, диспетчер драйверов копирует определенные ODBC поля, но не копирует определяемые драйвером поля или поля, которые не определены ODBC для типа дескриптора.

Вызов SQLCopyDesc прерывается немедленно, если возникает ошибка.

При копировании поля SQL_DESC_DATA_PTR проверка согласованности выполняется в целевом дескрипторе. Если проверка согласованности завершается ошибкой, возвращается sqlSTATE HY021 (несогласованные сведения дескриптора), а вызов SQLCopyDesc немедленно прерван. Дополнительные сведения о проверках согласованности см. в разделе "Проверки согласованности" в функции SQLSetDescRec.

Дескрипторные дескрипторы можно копировать между подключениями, даже если подключения находятся в разных средах. Если диспетчер драйверов обнаруживает, что дескриптор источника и конечного дескриптора не принадлежат одному соединению, а два подключения относятся к отдельным драйверам, он реализует SQLCopyDesc путем выполнения копирования по полю с помощью SQLGetDescField и SQLSetDescField.

При вызове SQLCopyDesc с sourceDescHandle на одном драйвере и TargetDescHandle на другом драйвере удаляется очередь ошибок SourceDescHandle. Это происходит, так как SQLCopyDesc в этом случае реализуется вызовами SQLGetDescField и SQLSetDescField.

Примечание.

Приложение может связать явно выделенный дескриптор дескриптор с оператором StatementHandle, а не вызывать SQLCopyDesc для копирования полей из одного дескриптора в другой. Явно выделенный дескриптор можно связать с другим оператором StatementHandle в том же ConnectionHandle, задав атрибут оператора SQL_ATTR_APP_ROW_DESC или SQL_ATTR_APP_PARAM_DESC для дескриптора явно выделенного дескриптора. После этого необходимо вызвать SQLCopyDesc для копирования значений полей дескриптора из одного дескриптора в другой. Дескриптор не может быть связан с оператором StatementHandle в другом ConnectionHandle, однако, чтобы использовать те же значения полей дескриптора в StatementHandles в разных ConnectionHandles, SQLCopyDesc необходимо вызвать.

Описание полей в заголовке дескриптора или записи см. в разделе "Функция SQLSetDescField". Дополнительные сведения о дескрипторах см. в разделе "Дескрипторы".

Копирование строк между таблицами

Приложение может копировать данные из одной таблицы в другую, не копируя данные на уровне приложения. Для этого приложение привязывает те же буферы данных и сведения дескриптора к инструкции, которая извлекает данные и инструкцию, которая вставляет данные в копию. Это можно сделать либо путем совместного использования дескриптора приложения (привязка явно выделенного дескриптора в качестве ARD к одной инструкции и APD в другой), либо с помощью SQLCopyDesc для копирования привязок между ARD и APD двух операторов. Если инструкции находятся в разных подключениях, необходимо использовать SQLCopyDesc . Кроме того, необходимо вызвать SQLCopyDesc для копирования привязок между IRD и IPD двух операторов. При копировании между операторами в том же соединении SQL_ACTIVE_STATEMENTS тип информации, возвращаемый драйвером для вызова SQLGetInfo , должен быть больше 1 для успешной операции. (Это не так при копировании между подключениями.)

Пример кода

В следующем примере операции дескриптора используются для копирования полей таблицы PartsSource в таблицу PartsCopy. Содержимое таблицы PartsSource извлекаются в буферы набора строк в hstmt0. Эти значения используются в качестве параметров инструкции INSERT в hstmt1 для заполнения столбцов таблицы PartsCopy. Для этого поля IRD hstmt0 копируются в поля IPD hstmt1, а поля ARD hstmt0 копируются в поля APD hstmt1. Используйте SQLSetDescField , чтобы задать атрибут SQL_DESC_PARAMETER_TYPE IPD SQL_PARAM_INPUT при копировании полей IRD из инструкции с выходными параметрами в поля IPD, которые должны быть входными параметрами.

#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

См. также

Справочник по API ODBC
Файлы заголовков ODBC