Функция 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 |