Função SQLCopyDesc

Conformidade
Versão introduzida: ODBC 3.0 Standards Compliance: 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 de 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).

Retornos

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 Identificador 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 deles 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 foi conectado falhou antes da conclusão do processamento da função.
HY000 Erro geral Ocorreu um erro para o qual não havia nenhum 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 instruçã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ções (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 do 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 de os dados serem 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 a SourceDescHandle ou TargetDescHandle e retornados SQL_PARAM_DATA_AVAILABLE. Essa função foi chamada antes de os dados serem 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 inconsistentes do descritor As informações do descritor verificadas durante uma verificação de consistência não eram 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 motivou uma chamada para SQLSetDescField, mas *ValuePtr não era válido para o argumento FieldIdentifier em TargetDescHandle.
HY117 A conexão é suspensa devido ao estado de transação desconhecido. 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 da fonte de dados responder à 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 dá suporte a essa 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 só podem ser copiados 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 retorna SQLSTATE HY007 (a instrução Associated não está preparada).

Os campos podem ser copiados de um IPD se uma instrução foi preparada ou não. Se uma instrução SQL com parâmetros dinâmicos tiver sido preparada e a população automática do IPD for compatível e habilitada, 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 automaticamente ou explicitamente), são copiados, independentemente de o campo ser definido ou não para o descritor de destino. Os campos copiados substituem os campos existentes.

O driver copiará todos os campos de 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á campos definidos por ODBC, mas não copiará campos definidos pelo driver ou campos que não são definidos pelo ODBC para o tipo de descritor.

A chamada para SQLCopyDesc será 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 de descritor inconsistentes) será retornada 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.

Identificadores de descritor podem ser copiados entre conexões mesmo se as conexões estiverem em ambientes diferentes. Se o Gerenciador de Driver detectar que as alças do descritor de origem e de destino não pertencem à mesma conexão e as duas conexões pertencem a drivers separados, ele implementa SQLCopyDesc executando uma cópia campo a 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 é desmarcada. 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 explicitamente alocado a um StatementHandle, em vez de chamar SQLCopyDesc para copiar campos de um descritor para outro. Um descritor explicitamente alocado 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 para o identificador do descritor explicitamente alocado. Quando isso é feito, o SQLCopyDesc não precisa ser chamado para copiar valores de campo do 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 ConnectionHandles diferentes, SQLCopyDesc precisa 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 de 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 explicitamente alocado como o ARD a uma instrução e a APD em outra) ou usando SQLCopyDesc para copiar as associações entre o ARD e a APD das duas instruções. Se as instruções estiverem em conexões diferentes, SQLCopyDesc deverá ser usado. Além disso, SQLCopyDesc precisa ser chamado para copiar as associações entre o IRD e o IPD das duas instruções. Ao copiar instruções na mesma conexão, o tipo de informações SQL_ACTIVE_STATEMENTS retornado pelo driver para uma chamada para SQLGetInfo deve ser maior que 1 para que essa operação tenha êxito. (Esse 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 no hstmt0. Esses valores são usados como parâmetros de uma instrução INSERT no hstmt1 para preencher as colunas da tabela PartsCopy. Para fazer 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 da APD de hstmt1. Use SQLSetDescField para definir o atributo SQL_DESC_PARAMETER_TYPE do IPD como SQL_PARAM_INPUT quando você 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  
Para obter informações sobre Consulte
Obtendo vários campos de descritor Função SQLGetDescRec
Configurando um único campo de descritor Função SQLSetDescField
Configurando vários campos de descritor Função SQLSetDescRec

Consulte Também

Referência de API do ODBC
Arquivos de cabeçalho ODBC