Função SQLCopyDesc
Compatibilidade
Versão introduzida: ODBC 3.0 Conformidade com os padrões: ISO 92
Resumo
SQLCopyDesc copia informações do descritor de um identificador de descritor para outro.
Sintaxe
SQLRETURN SQLCopyDesc(
SQLHDESC SourceDescHandle,
SQLHDESC TargetDescHandle);
Argumentos
SourceDescHandle
[Entrada] Identificador do descritor de origem.
TargetDescHandle
[Entrada] Identificador do descritor de destino. O argumento TargetDescHandle pode ser um identificador para um descritor de aplicativo ou um IPD. TargetDescHandle não pode ser definido como um identificador para um IRD ou SQLCopyDesc retornará SQLSTATE HY016 (não é possível modificar um descritor de linha de implementação).
Devoluções
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR ou SQL_INVALID_HANDLE.
Diagnósticos
Quando SQLCopyDesc retorna SQL_ERROR ou SQL_SUCCESS_WITH_INFO, um valor SQLSTATE associado pode ser obtido chamando SQLGetDiagRec com um HandleType de SQL_HANDLE_DESC e um Handle de TargetDescHandle. Se um SourceDescHandle inválido tiver sido passado na chamada, SQL_INVALID_HANDLE será retornado, mas nenhum SQLSTATE será retornado. A tabela a seguir lista os valores SQLSTATE normalmente retornados por SQLCopyDesc e explica cada um no contexto dessa função; a notação "(DM)" precede as descrições de SQLSTATEs retornadas pelo Gerenciador de Driver. O código de retorno associado a cada valor SQLSTATE é SQL_ERROR, a menos que indicado de outra forma.
Quando um erro é retornado, a chamada para SQLCopyDesc é imediatamente anulada e o conteúdo dos campos no descritor TargetDescHandle é indefinido.
Como SQLCopyDesc pode ser implementado chamando SQLGetDescField e SQLSetDescField, SQLCopyDesc pode retornar SQLSTATEs retornados por SQLGetDescField ou SQLSetDescField.
SQLSTATE | Erro | Descrição |
---|---|---|
01000 | Aviso geral | Mensagem informativa específica do driver. (A função retorna SQL_SUCCESS_WITH_INFO.) |
08S01 | Falha no link de comunicação | O link de comunicação entre o driver e a fonte de dados à qual o driver estava conectado falhou antes que a função concluísse o processamento. |
HY000 | Erro geral | Ocorreu um erro para o qual não havia SQLSTATE específico e para o qual nenhum SQLSTATE específico da implementação foi definido. A mensagem de erro retornada por SQLGetDiagRec no buffer *MessageText descreve o erro e sua causa. |
HY001 | Erro de alocação de memória | O driver não pôde alocar a memória necessária para dar suporte à execução ou conclusão da função. |
HY007 | A declaração associada não está preparada | SourceDescHandle foi associado a um IRD e o identificador de instrução associado não estava no estado preparado ou executado. |
HY010 | Erro de sequência de função | (DM) O identificador de descritor em SourceDescHandle ou TargetDescHandle foi associado a um StatementHandle para o qual uma função de execução assíncrona (não esta) foi chamada e ainda estava em execução quando essa função foi chamada. (DM) O identificador de descritor em SourceDescHandle ou TargetDescHandle foi associado a um StatementHandle para o qual SQLExecute, SQLExecDirect, SQLBulkOperations ou SQLSetPos foi chamado e retornado SQL_NEED_DATA. Essa função foi chamada antes que os dados fossem enviados para todos os parâmetros ou colunas de dados em execução. (DM) Uma função de execução assíncrona foi chamada para o identificador de conexão associado ao SourceDescHandle ou TargetDescHandle. Essa função assíncrona ainda estava em execução quando a função SQLCopyDesc foi chamada. (DM) SQLExecute, SQLExecDirect ou SQLMoreResults foi chamado para um dos identificadores de instrução associados ao SourceDescHandle ou TargetDescHandle e retornou SQL_PARAM_DATA_AVAILABLE. Essa função foi chamada antes que os dados fossem recuperados para todos os parâmetros transmitidos. |
HY013 | Erro de gerenciamento de memória | A chamada de função não pôde ser processada porque os objetos de memória subjacentes não puderam ser acessados, possivelmente devido a condições de memória baixa. |
HY016 | Não é possível modificar um descritor de linha de implementação | TargetDescHandle foi associado a um IRD. |
HY021 | Informações de descritor inconsistentes | As informações do descritor verificadas durante uma verificação de consistência não foram consistentes. Para obter mais informações, consulte "Verificações de consistência" em SQLSetDescField. |
HY092 | Identificador de atributo/opção inválido | A chamada para SQLCopyDesc solicitou uma chamada para SQLSetDescField, mas *ValuePtr não era válido para o argumento FieldIdentifier em TargetDescHandle. |
HY117 | A conexão está suspensa devido ao estado desconhecido da transação. Somente funções de desconexão e somente leitura são permitidas. | (DM) Para obter mais informações sobre o estado suspenso, consulte Função SQLEndTran. |
HYT01 | O tempo limite da conexão expirou | O período de tempo limite da conexão expirou antes que a fonte de dados respondesse à solicitação. O período de tempo limite da conexão é definido por meio de SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT. |
IM001 | O driver não suporta esta função | (DM) O driver associado ao SourceDescHandle ou TargetDescHandle não dá suporte à função. |
Comentários
Uma chamada para SQLCopyDesc copia os campos do identificador do descritor de origem para o identificador do descritor de destino. Os campos podem ser copiados apenas para um descritor de aplicativo ou um IPD, mas não para um IRD. Os campos podem ser copiados de um aplicativo ou de um descritor de implementação.
Os campos só poderão ser copiados de um IRD se o identificador de instrução estiver no estado preparado ou executado; caso contrário, a função retornará SQLSTATE HY007 (a instrução associada não está preparada).
Os campos podem ser copiados de um IPD, independentemente de uma instrução ter sido preparada ou não. Se uma instrução SQL com parâmetros dinâmicos tiver sido preparada e o preenchimento automático do IPD tiver suporte e habilitado, o IPD será preenchido pelo driver. Quando SQLCopyDesc é chamado com o IPD como SourceDescHandle, os campos preenchidos são copiados. Se o IPD não for preenchido pelo driver, o conteúdo dos campos originalmente no IPD será copiado.
Todos os campos do descritor, exceto SQL_DESC_ALLOC_TYPE (que especifica se o identificador do descritor foi alocado automática ou explicitamente), são copiados, independentemente de o campo estar ou não definido para o descritor de destino. Os campos copiados substituem os campos existentes.
O driver copiará todos os campos do descritor se os argumentos SourceDescHandle e TargetDescHandle estiverem associados ao mesmo driver, mesmo que os drivers estejam em duas conexões ou ambientes diferentes. Se os argumentos SourceDescHandle e TargetDescHandle estiverem associados a drivers diferentes, o Gerenciador de Driver copiará os campos definidos pelo ODBC, mas não copiará os campos definidos pelo driver ou os campos que não são definidos pelo ODBC para o tipo de descritor.
A chamada para SQLCopyDesc é anulada imediatamente se ocorrer um erro.
Quando o campo SQL_DESC_DATA_PTR é copiado, uma verificação de consistência é executada no descritor de destino. Se a verificação de consistência falhar, SQLSTATE HY021 (informações do descritor inconsistente) será retornado e a chamada para SQLCopyDesc será imediatamente anulada. Para obter mais informações sobre verificações de consistência, consulte "Verificações de consistência" na função SQLSetDescRec.
Os identificadores de descritor podem ser copiados entre conexões, mesmo que as conexões estejam em ambientes diferentes. Se o Gerenciador de Driver detectar que os identificadores de descritor de origem e destino não pertencem à mesma conexão e as duas conexões pertencem a drivers separados, ele implementará SQLCopyDesc executando uma cópia campo por campo usando SQLGetDescField e SQLSetDescField.
Quando SQLCopyDesc é chamado com um SourceDescHandle em um driver e um TargetDescHandle em outro driver, a fila de erros do SourceDescHandle é limpa. Isso ocorre porque SQLCopyDesc nesse caso é implementado por chamadas para SQLGetDescField e SQLSetDescField.
Observação
Um aplicativo pode ser capaz de associar um identificador de descritor alocado explicitamente a um StatementHandle, em vez de chamar SQLCopyDesc para copiar campos de um descritor para outro. Um descritor alocado explicitamente pode ser associado a outro StatementHandle no mesmo ConnectionHandle definindo o atributo de instrução SQL_ATTR_APP_ROW_DESC ou SQL_ATTR_APP_PARAM_DESC como o identificador do descritor alocado explicitamente. Quando isso é feito, SQLCopyDesc não precisa ser chamado para copiar valores de campo de descritor de um descritor para outro. No entanto, um identificador de descritor não pode ser associado a um StatementHandle em outro ConnectionHandle; para usar os mesmos valores de campo de descritor em StatementHandles em diferentes ConnectionHandles, SQLCopyDesc deve ser chamado.
Para obter uma descrição dos campos em um cabeçalho ou registro de descritor, consulte Função SQLSetDescField. Para obter mais informações sobre descritores, consulte Descritores.
Copiando linhas entre tabelas
Um aplicativo pode copiar dados de uma tabela para outra sem copiar os dados no nível do aplicativo. Para fazer isso, o aplicativo associa os mesmos buffers de dados e informações do descritor a uma instrução que busca os dados e a instrução que insere os dados em uma cópia. Isso pode ser feito compartilhando um descritor de aplicativo (associando um descritor alocado explicitamente como o ARD a uma instrução e o APD em outra) ou usando SQLCopyDesc para copiar as associações entre o ARD e o APD das duas instruções. Se as instruções estiverem em conexões diferentes, SQLCopyDesc deverá ser usado. Além disso, SQLCopyDesc deve ser chamado para copiar as associações entre o IRD e o IPD das duas instruções. Ao copiar entre instruções na mesma conexão, o tipo de informação SQL_ACTIVE_STATEMENTS retornado pelo driver para uma chamada para SQLGetInfo deve ser maior que 1 para que essa operação seja bem-sucedida. (Este não é o caso ao copiar entre conexões.)
Exemplo de código
No exemplo a seguir, as operações de descritor são usadas para copiar os campos da tabela PartsSource para a tabela PartsCopy. O conteúdo da tabela PartsSource é buscado em buffers de conjunto de linhas em hstmt0. Esses valores são usados como parâmetros de uma instrução INSERT em hstmt1 para preencher as colunas da tabela PartsCopy. Para isso, os campos do IRD de hstmt0 são copiados para os campos do IPD de hstmt1, e os campos do ARD de hstmt0 são copiados para os campos do APD de hstmt1. Use SQLSetDescField para definir o atributo SQL_DESC_PARAMETER_TYPE do IPD como SQL_PARAM_INPUT ao copiar campos IRD de uma instrução com parâmetros de saída para campos IPD que precisam ser parâmetros de entrada.
#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
Funções relacionadas
Para obter informações sobre | Consulte |
---|---|
Obtendo vários campos de descritor | Função SQLGetDescRec |
Definindo um único campo de descritor | Função SQLSetDescField |
Configurando vários campos de descritor | Função SQLSetDescRec |