Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Conformidade
Versão Introduzida: Conformidade com as Normas ODBC 3.0: ODBC
Summary
O SQLBulkOperations realiza inserções em massa e operações de marcadores em massa, incluindo atualização, eliminação e obtenção por marcador de favoritos.
Syntax
SQLRETURN SQLBulkOperations(
SQLHSTMT StatementHandle,
SQLUSMALLINT Operation);
Arguments
HandleStatement
[Entrada] Identificador do extrato.
Funcionamento
[Entrada] Operação a realizar:
SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK
Para mais informações, consulte "Comentários."
Devoluções
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR ou SQL_INVALID_HANDLE.
Diagnósticos
Quando o SQLBulkOperations retorna SQL_ERROR ou SQL_SUCCESS_WITH_INFO, um valor SQLSTATE associado pode ser obtido chamando SQLGetDiagRec com um HandleType de SQL_HANDLE_STMT e um Handle de StatementHandle. A tabela seguinte lista os valores SQLSTATE normalmente devolvidos pelo SQLBulkOperations e explica cada um no contexto desta função; a notação "(DM)" precede as descrições dos SQLSTATEs devolvidas pelo Gestor de Drivers. O código de retorno associado a cada valor SQLSTATE é SQL_ERROR, salvo indicação em contrário.
Para todos os SQLSTATEs que podem devolver SQL_SUCCESS_WITH_INFO ou SQL_ERROR (exceto 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO é devolvido se ocorrer um erro numa ou mais, mas não todas, linhas de uma operação de várias linhas, e SQL_ERROR é devolvido se ocorrer um erro numa operação de uma única linha.
| SQLSTATE | Erro | Description |
|---|---|---|
| 01000 | Aviso geral | Mensagem informativa específica para o condutor. (Função devolve SQL_SUCCESS_WITH_INFO.) |
| 01004 | Truncamento à direita dos dados da cadeia | O argumento Operação era SQL_FETCH_BY_BOOKMARK, e dados de string ou binários devolvidos para uma coluna ou colunas com um tipo de dado SQL_C_CHAR ou SQL_C_BINARY resultavam na truncação de caracteres não em branco ou dados binários não NULL. |
| 01S01 | Erro em linha | O argumento Operação foi SQL_ADD, e ocorreu um erro numa ou mais linhas durante a execução da operação, mas pelo menos uma linha foi adicionada com sucesso. (Função devolve SQL_SUCCESS_WITH_INFO.) (Este erro só surge quando uma aplicação está a trabalhar com um ODBC 2. x condutor.) |
| 01S07 | Truncamento fracionado | O argumento Operação era SQL_FETCH_BY_BOOKMARK, o tipo de dado do buffer de aplicação não era SQL_C_CHAR nem SQL_C_BINARY, e os dados devolvidos aos buffers de aplicação para uma ou mais colunas eram truncados. (Para os tipos de dados numéricos C, a parte fracionária do número era truncada. Para tipos de dados de tempo, carimbo temporal e intervalo C que contêm um componente temporal, a porção fracionária do tempo foi truncada.) (Função devolve SQL_SUCCESS_WITH_INFO.) |
| 07006 | Violação de atributo de tipo de dado restrito | O argumento Operação era SQL_FETCH_BY_BOOKMARK, e o valor de dados de uma coluna no conjunto de resultados não podia ser convertido para o tipo de dado especificado pelo argumento TargetType na chamada ao SQLBindCol. O argumento Operação era SQL_UPDATE_BY_BOOKMARK ou SQL_ADD, e o valor dos dados nos buffers da aplicação não podia ser convertido para o tipo de dados de uma coluna no conjunto de resultados. |
| 07009 | Índice de descritores inválido | A Operação de argumento era SQL_ADD, e uma coluna era limitada com um número de colunas maior do que o número de colunas no conjunto de resultados. |
| 21S02 | O grau da tabela derivada não corresponde à lista de colunas | A Operação de argumentos foi SQL_UPDATE_BY_BOOKMARK; e nenhuma coluna era atualizável porque todas as colunas eram não vinculadas ou só de leitura, ou o valor no buffer de comprimento/indicador limitado era SQL_COLUMN_IGNORE. |
| 22001 | Truncamento à direita dos dados da cadeia | A atribuição de um carácter ou valor binário a uma coluna no conjunto de resultados resultava na truncação de caracteres ou bytes não em branco (para caracteres) ou não nulos (para binários). |
| 22003 | Valor numérico fora do intervalo | O argumento Operação era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK, e a atribuição de um valor numérico a uma coluna no conjunto de resultados fazia com que toda a parte (em vez de fracionária) do número fosse truncada. O argumento Operação era SQL_FETCH_BY_BOOKMARK, e devolver o valor numérico de uma ou mais colunas ligadas teria causado uma perda significativa de dígitos. |
| 22007 | Formato de data-hora inválido | O argumento Operação era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK, e a atribuição de um valor de data ou hora a uma coluna no conjunto de resultados fazia com que o campo do ano, mês ou dia ficasse fora do alcance. A Operação de argumento era SQL_FETCH_BY_BOOKMARK, e devolver o valor da data ou hora de uma ou mais colunas encadernadas teria feito com que o campo do ano, mês ou dia ficasse fora do alcance. |
| 22008 | Excedente de campo data/hora | O argumento Operação era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK, e a execução da aritmética de data-hora nos dados enviados para uma coluna do conjunto de resultados resultava num campo de data-hora (o ano, mês, dia, hora, minuto ou segundo campo) do resultado fora do intervalo permitido de valores para o campo ou inválido segundo as regras naturais do calendário gregoriano para datas-horas. O argumento da Operação era SQL_FETCH_BY_BOOKMARK, e o desempenho da aritmética de data-hora nos dados recolhidos do conjunto de resultados resultava num campo de data-hora (o ano, mês, dia, hora, minuto ou segundo campo) do resultado fora do intervalo permitido de valores para o campo ou inválido com base nas regras naturais do calendário gregoriano para datas-horas. |
| 22015 | Excesso de campo de intervalo | O argumento Operação era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK, e a atribuição de um tipo numérico ou C de intervalo exato a um tipo de dados SQL de intervalo causava uma perda significativa de dígitos. O argumento da Operação era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK; ao atribuir a um tipo SQL de intervalo, não havia representação do valor do tipo C no tipo SQL de intervalo. O argumento de Operação era SQL_FETCH_BY_BOOKMARK, e atribuir de um tipo SQL numérico ou de intervalo exato a um tipo C de intervalo causava uma perda de dígitos significativos no campo principal. O argumento da Operação era SQL_FETCH_BY_BOOKMARK; ao atribuir a um intervalo o tipo C, não havia representação do valor do tipo SQL no tipo de intervalo C. |
| 22018 | Valor de personagem inválido para especificação de elenco | O argumento da Operação era SQL_FETCH_BY_BOOKMARK; o tipo C era um número exato ou aproximado, um data-hora ou um tipo de dado de intervalo; o tipo SQL da coluna era um tipo de dado de carácter; e o valor na coluna não era um literal válido do tipo C limitado. A Operação de discussão era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK; o tipo SQL era um tipo numérico exato ou aproximado, um data-hora ou um tipo de dado de intervalo; o tipo C era SQL_C_CHAR; e o valor na coluna não era um literal válido do tipo SQL limitado. |
| 23000 | Violação de restrições de integridade | O argumento da Operação era SQL_ADD, SQL_DELETE_BY_BOOKMARK ou SQL_UPDATE_BY_BOOKMARK, e uma restrição de integridade foi violada. O argumento Operação era SQL_ADD, e uma coluna que não estava limitada é definida como NÃO NULA e não tem padrão. O argumento Operação era SQL_ADD, o comprimento especificado no buffer de StrLen_or_IndPtr limitado era SQL_COLUMN_IGNORE, e a coluna não tinha valor padrão. |
| 24000 | Estado do cursor inválido | O StatementHandle estava num estado executado, mas nenhum conjunto de resultados estava associado ao StatementHandle. |
| 40001 | Falha de serialização | A transação foi revertida devido a um bloqueio de recursos com outra transação. |
| 40003 | Conclusão da afirmação desconhecida | A ligação associada falhou durante a execução desta função, e o estado da transação não pode ser determinado. |
| 42000 | Erro de sintaxe ou violação de acesso | O condutor não conseguiu bloquear a linha como necessário para realizar a operação solicitada no argumento Operação . |
| 44000 | COM VIOLAÇÃO DA OPÇÃO DE VERIFICAÇÃO | O argumento Operação era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK, e a inserção ou atualização era realizada numa tabela visualizada (ou numa tabela derivada da tabela visualizada) criada especificando COM CHECK OPTION, de modo a que uma ou mais linhas afetadas pela inserção ou atualização deixassem de estar presentes na tabela visualizada. |
| HY000 | Erro geral | Ocorreu um erro para o qual não existia um SQLSTATE específico e para o qual não estava definido nenhum SQLSTATE específico da implementação. A mensagem de erro devolvida pelo SQLGetDiagRec no buffer *MessageText descreve o erro e a sua causa. |
| HY001 | Erro de alocação de memória | O driver não conseguia alocar a memória necessária para suportar a execução ou conclusão da função. |
| HY008 | Operação cancelada | O processamento assíncrono foi ativado para o StatementHandle. A função era chamada e, antes de terminar a execução, o SQLCancel ou SQLCancelHandle era chamado no StatementHandle. Depois, a função era chamada novamente no StatementHandle. A função era chamada e, antes de terminar a execução, o SQLCancel ou SQLCancelHandle era chamado no StatementHandle a partir de um thread diferente numa aplicação multithread. |
| HY010 | Erro de sequência de funções | (DM) Uma função de execução assíncrona era chamada para o handle de ligação associado ao StatementHandle. Esta função assíncrona ainda estava a ser executada quando a função SQLBulkOperations foi chamada. (DM) SQLExecute, SQLExecDirect ou SQLMoreResults era chamado para o StatementHandle e devolvido SQL_PARAM_DATA_AVAILABLE. Esta função era chamada antes de os dados serem recuperados para todos os parâmetros transmitidos. (DM) O HandleStatement especificado não estava num estado executado. A função era chamada sem antes chamar SQLExecDirect, SQLExecute ou uma função de catálogo. (DM) Uma função de execução assíncrona (não esta) era chamada para o StatementHandle e continuava a ser executada quando esta função era chamada. (DM) SQLExecute, SQLExecDirect ou SQLSetPos era chamado para o StatementHandle e retornava SQL_NEED_DATA. Esta função era chamada antes de os dados serem enviados para todos os parâmetros ou colunas de dados na execução. (DM) O condutor era um ODBC 2. x , e SQLBulkOperations era chamado para um StatementHandle antes de SQLFetchScroll ou SQLFetch serem chamados. (DM) SQLBulkOperations foi chamado depois de o SQLExtendedFetch ter sido chamado no StatementHandle. |
| HY011 | O atributo não pode ser definido agora | (DM) O condutor era um ODBC 2. x , e o atributo da instrução SQL_ATTR_ROW_STATUS_PTR era definido entre chamadas para SQLFetch ou SQLFetchScroll e SQLBulkOperations. |
| HY013 | Erro de gestão de memória | A chamada de função não podia ser processada porque os objetos de memória subjacentes não podiam ser acedidos, possivelmente devido a condições de baixa memória. |
| HY090 | Comprimento inválido da corda ou do buffer | O argumento da Operação era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK; um valor de dado não era um ponteiro nulo; o tipo de dados C era SQL_C_BINARY ou SQL_C_CHAR; e o valor do comprimento da coluna era inferior a 0, mas não igual a SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NTS ou SQL_NULL_DATA, ou menor ou igual a SQL_LEN_DATA_AT_EXEC_OFFSET. O valor num buffer de comprimento/indicador era SQL_DATA_AT_EXEC; o tipo SQL era ou SQL_LONGVARCHAR, SQL_LONGVARBINARY ou um tipo longo específico de fonte de dados; e o SQL_NEED_LONG_DATA_LEN tipo de informação em SQLGetInfo era "Y". O argumento Operação era SQL_ADD, o atributo da instrução SQL_ATTR_USE_BOOKMARK era definido para SQL_UB_VARIABLE, e a coluna 0 era atribuída a um buffer cujo comprimento não era igual ao comprimento máximo do marcador para este conjunto de resultados. (Este comprimento está disponível no campo SQL_DESC_OCTET_LENGTH do IRD e pode ser obtido chamando SQLDescribeCol, SQLColAttributes ou SQLGetDescField.) |
| HY092 | Identificador de atributo inválido | (DM) O valor especificado para o argumento Operação era inválido. O argumento da Operação era SQL_ADD, SQL_UPDATE_BY_BOOKMARK ou SQL_DELETE_BY_BOOKMARK, e o atributo da declaração SQL_ATTR_CONCURRENCY era definido como SQL_CONCUR_READ_ONLY. O argumento da Operação era SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK ou SQL_UPDATE_BY_BOOKMARK, e a coluna do marcador não estava encadernada ou o atributo SQL_ATTR_USE_BOOKMARKS da instrução estava definido para SQL_UB_OFF. |
| HY117 | A ligação é suspensa devido ao estado desconhecido da transação. Apenas funções de desconexão e de leitura são permitidas. | (DM) Para mais informações sobre o estado suspenso, veja Função SQLEndTran. |
| HYC00 | Funcionalidade opcional não implementada | O driver ou fonte de dados não suporta a operação solicitada no argumento de Operação . |
| HYT00 | O tempo limite expirou | O período de tempo de espera da consulta expirava antes de a fonte de dados devolver o conjunto de resultados. O período de timeout é definido através do SQLSetStmtAttr com um argumento de Atributo de SQL_ATTR_QUERY_TIMEOUT. |
| HYT01 | Expirou o tempo limite de ligação | O período de timeout da ligação expirou antes de a fonte de dados responder ao pedido. O período de tempo de expiração da ligação é definido através do SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT. |
| IM001 | O driver não suporta esta função | (DM) O driver associado ao StatementHandle não suporta a função. |
| IM017 | A sondagem está desativada no modo de notificação assíncrona | Sempre que o modelo de notificação é utilizado, o sonding é desativado. |
| IM018 | O SQLCompleteAsync não foi chamado para completar a operação assíncrona anterior neste handle. | Se a chamada de função anterior no handle devolver SQL_STILL_EXECUTING e se o modo de notificação estiver ativado, o SQLCompleteAsync deve ser chamado no handle para fazer o pós-processamento e completar a operação. |
Comments
Caution
Para informações sobre que estados de instruções SQLBulkOperations pode ser chamado e o que deve fazer para compatibilidade com o ODBC 2. x aplicações, consulte a secção Block Cursors, Scrollable Cursors, and Backward Compatibility no Apêndice G: Diretrizes de Drivers para Retrocompatibilidade.
Uma aplicação utiliza SQLBulkOperations para realizar as seguintes operações na tabela base ou visualização que corresponde à consulta atual:
Adiciona novas linhas.
Atualize um conjunto de linhas onde cada linha é identificada por um favorito.
Apague um conjunto de linhas onde cada linha é identificada por um favorito.
Vá buscar um conjunto de linhas onde cada linha é identificada por um marcador.
Após uma chamada ao SQLBulkOperations, a posição do cursor de bloco permanece indefinida. A aplicação tem de chamar SQLFetchScroll para definir a posição do cursor. Uma aplicação deve chamar SQLFetchScroll apenas com um argumento FetchOrientation de SQL_FETCH_FIRST, SQL_FETCH_LAST, SQL_FETCH_ABSOLUTE ou SQL_FETCH_BOOKMARK. A posição do cursor é indefinida se a aplicação chamar SQLFetch ou SQLFetchScroll com um argumento FetchOrientation de SQL_FETCH_PRIOR, SQL_FETCH_NEXT ou SQL_FETCH_RELATIVE.
Uma coluna pode ser ignorada em operações em massa realizadas por uma chamada ao SQLBulkOperations ao definir o comprimento/buffer indicador da coluna especificado na chamada ao SQLBindCol para SQL_COLUMN_IGNORE.
Não é necessário que a aplicação defina o atributo da instrução SQL_ATTR_ROW_OPERATION_PTR quando chama SQLBulkOperations porque as linhas não podem ser ignoradas ao realizar operações em massa com esta função.
O buffer apontado pelo atributo da instrução SQL_ATTR_ROWS_FETCHED_PTR contém o número de linhas afetadas por uma chamada para SQLBulkOperations.
Quando o argumento Operação está SQL_ADD ou SQL_UPDATE_BY_BOOKMARK e a lista de seleção da especificação de consulta associada ao cursor contém mais do que uma referência à mesma coluna, é definido pelo driver se um erro é gerado ou se o driver ignora as referências duplicadas e realiza as operações solicitadas.
Para mais informações sobre como usar SQLBulkOperations, consulte Atualizar Dados com SQLBulkOperations.
Execução de Inserções em Massa
Para inserir dados com SQLBulkOperations, uma aplicação executa a seguinte sequência de passos:
Executa uma consulta que devolve um conjunto de resultados.
Define o atributo da instrução SQL_ATTR_ROW_ARRAY_SIZE ao número de linhas que quer inserir.
Chama o SQLBindCol para vincular os dados que pretende inserir. Os dados estão ligados a um array com tamanho igual ao valor de SQL_ATTR_ROW_ARRAY_SIZE.
Note
O tamanho do array apontado pelo atributo SQL_ATTR_ROW_STATUS_PTR da instrução deve ser igual a SQL_ATTR_ROW_ARRAY_SIZE ou SQL_ATTR_ROW_STATUS_PTR deve ser um ponteiro nulo.
Chama SQLBulkOperations(StatementHandle, SQL_ADD) para realizar a inserção.
Se a aplicação definiu o atributo SQL_ATTR_ROW_STATUS_PTR de instrução, pode inspecionar este array para ver o resultado da operação.
Se uma aplicação ligar a coluna 0 antes de chamar SQLBulkOperations com um argumento Operation de SQL_ADD, o driver irá atualizar os buffers da coluna 0 com os valores de favoritos da linha recém-inserida. Para que isso aconteça, a aplicação deve ter definido o atributo da SQL_ATTR_USE_BOOKMARKS para SQL_UB_VARIABLE antes de executar a instrução. (Isto não funciona com um ODBC 2. x condutor.)
Os dados longos podem ser adicionados em partes pelo SQLBulkOperations, usando chamadas para SQLParamData e SQLPutData. Para mais informações, veja "Fornecer Dados Longos para Inserções e Atualizações em Massa" mais adiante nesta referência de função.
Não é necessário que a aplicação chame SQLFetch ou SQLFetchScroll antes de chamar SQLBulkOperations (exceto quando se enfrenta a um ODBC 2.condutor X ; ver Compatibilidade Retrocedente e Conformidade de Normas).
O comportamento é definido pelo driver se o SQLBulkOperations, com um argumento Operation de SQL_ADD, for chamado num cursor que contém colunas duplicadas. O driver pode devolver um SQLSTATE definido pelo driver, adicionar os dados à primeira coluna que aparece no conjunto de resultados, ou executar outros comportamentos definidos pelo driver.
Realização de Atualizações em Massa através do Uso de Marcadores
Para realizar atualizações em massa usando favoritos com SQLBulkOperations, uma aplicação executa os seguintes passos em sequência:
Define o atributo da SQL_ATTR_USE_BOOKMARKS de instrução para SQL_UB_VARIABLE.
Executa uma consulta que devolve um conjunto de resultados.
Define o atributo da instrução SQL_ATTR_ROW_ARRAY_SIZE ao número de linhas que quer atualizar.
Chama o SQLBindCol para vincular os dados que quer atualizar. Os dados estão ligados a um array com tamanho igual ao valor de SQL_ATTR_ROW_ARRAY_SIZE. Também chama o SQLBindCol para atribuir a coluna 0 (a coluna de marcadores).
Copia os favoritos das linhas que pretende atualizar para o array ligado à coluna 0.
Atualiza os dados nos buffers vinculados.
Note
O tamanho do array apontado pelo atributo da instrução SQL_ATTR_ROW_STATUS_PTR deve ser igual a SQL_ATTR_ROW_ARRAY_SIZE ou SQL_ATTR_ROW_STATUS_PTR deve ser um ponteiro nulo.
Chamadas SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).
Note
Se a aplicação definiu o atributo SQL_ATTR_ROW_STATUS_PTR de instrução, pode inspecionar este array para ver o resultado da operação.
Opcionalmente, chama SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) para obter dados nos buffers de aplicação vinculados e verificar se a atualização ocorreu.
Se os dados forem atualizados, o driver altera o valor no array de estado das linhas para que as linhas apropriadas SQL_ROW_UPDATED.
As atualizações em massa realizadas pelo SQLBulkOperations podem incluir dados longos ao usar chamadas para SQLParamData e SQLPutData. Para mais informações, veja "Fornecer Dados Longos para Inserções e Atualizações em Massa" mais adiante nesta referência de função.
Se os marcadores persistirem através dos cursores, a aplicação não precisa de chamar SQLFetch ou SQLFetchScroll antes de atualizar através dos marcadores. Pode usar marcadores que guardou de um cursor anterior. Se os marcadores não persistirem através dos cursores, a aplicação tem de chamar SQLFetch ou SQLFetchScroll para recuperar os marcadores.
O comportamento é definido pelo driver se SQLBulkOperations, com um argumento Operation de SQL_UPDATE_BY_BOOKMARK, for chamado num cursor que contenha colunas duplicadas. O driver pode devolver um SQLSTATE definido pelo driver, atualizar a primeira coluna que aparece no conjunto de resultados ou executar outros comportamentos definidos pelo driver.
Realização de Buscas em Massa Usando Marcadores
Para realizar buscas em massa usando marcadores com SQLBulkOperations, uma aplicação executa os seguintes passos em sequência:
Define o atributo da SQL_ATTR_USE_BOOKMARKS de instrução para SQL_UB_VARIABLE.
Executa uma consulta que devolve um conjunto de resultados.
Define o atributo da instrução SQL_ATTR_ROW_ARRAY_SIZE ao número de linhas que quer buscar.
Chama o SQLBindCol para vincular os dados que quer recolher. Os dados estão ligados a um array com tamanho igual ao valor de SQL_ATTR_ROW_ARRAY_SIZE. Também chama o SQLBindCol para atribuir a coluna 0 (a coluna de marcadores).
Copia os marcadores das linhas que pretende obter para o array vinculado à coluna 0. (Isto pressupõe que a aplicação já obteve os marcadores separadamente.)
Note
O tamanho do array apontado pelo atributo da instrução SQL_ATTR_ROW_STATUS_PTR deve ser igual a SQL_ATTR_ROW_ARRAY_SIZE ou SQL_ATTR_ROW_STATUS_PTR deve ser um ponteiro nulo.
Chamadas SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK).
Se a aplicação definiu o atributo SQL_ATTR_ROW_STATUS_PTR de instrução, pode inspecionar este array para ver o resultado da operação.
Se os marcadores persistirem através dos cursores, a aplicação não precisa de chamar o SQLFetch ou SQLFetchScroll antes de buscar os marcadores. Pode usar marcadores que guardou de um cursor anterior. Se os marcadores não persistirem entre os cursores, a aplicação tem de chamar SQLFetch ou SQLFetchScroll uma vez para recuperar os marcadores.
Realização de Eliminações em Massa Usando Favoritos
Para realizar eliminações em massa usando favoritos com SQLBulkOperations, uma aplicação executa os seguintes passos em sequência:
Define o atributo da SQL_ATTR_USE_BOOKMARKS de instrução para SQL_UB_VARIABLE.
Executa uma consulta que devolve um conjunto de resultados.
Define o atributo da instrução SQL_ATTR_ROW_ARRAY_SIZE ao número de linhas que quer eliminar.
Chama SQLBindCol para atribuir a coluna 0 (a coluna de marcadores).
Copia os favoritos das linhas que está interessado em eliminar para o array vinculado à coluna 0.
Note
O tamanho do array apontado pelo atributo da instrução SQL_ATTR_ROW_STATUS_PTR deve ser igual a SQL_ATTR_ROW_ARRAY_SIZE ou SQL_ATTR_ROW_STATUS_PTR deve ser um ponteiro nulo.
Chama SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK).
Se a aplicação definiu o atributo SQL_ATTR_ROW_STATUS_PTR de instrução, pode inspecionar este array para ver o resultado da operação.
Se os marcadores persistirem entre os cursores, a aplicação não precisa de chamar SQLFetch ou SQLFetchScroll antes de eliminar pelos marcadores. Pode usar marcadores que guardou de um cursor anterior. Se os marcadores não persistirem entre os cursores, a aplicação tem de chamar SQLFetch ou SQLFetchScroll uma vez para recuperar os marcadores.
Fornecimento de dados longos para inserções e atualizações em massa
Podem ser fornecidos dados longos para inserções e atualizações em massa realizadas por chamadas ao SQLBulkOperations. Para inserir ou atualizar dados longos, uma aplicação executa os seguintes passos, além dos descritos nas secções "Realizar Inserções em Massa" e "Realizar Atualizações em Massa Usando Marcadores" anteriormente neste tópico.
Quando vincula os dados usando SQLBindCol, a aplicação coloca um valor definido pela aplicação, como o número da coluna, no buffer *TargetValuePtr para colunas de dados na execução. O valor pode ser usado mais tarde para identificar a coluna.
A aplicação coloca o resultado da macro SQL_LEN_DATA_AT_EXEC(comprimento) no buffer *StrLen_or_IndPtr . Se o tipo de dados SQL da coluna for SQL_LONGVARBINARY, SQL_LONGVARCHAR ou um tipo longo específico de fonte de dados e o driver devolver "Y" para o tipo de informação SQL_NEED_LONG_DATA_LEN em SQLGetInfo, o comprimento é o número de bytes de dados a enviar para o parâmetro; caso contrário, deve ser um valor não negativo e é ignorado.
Quando o SQLBulkOperations é chamado, se existirem colunas de dados na execução, a função devolve SQL_NEED_DATA e avança para o passo 3, que se segue. (Se não existirem colunas de dados na execução, o processo está concluído.)
A aplicação chama SQLParamData para recuperar o endereço do buffer *TargetValuePtr para a primeira coluna de dados na execução a ser processada. SQLParamData devolve SQL_NEED_DATA. A aplicação recupera o valor definido pela aplicação do buffer *TargetValuePtr .
Note
Embora os parâmetros data-at-execution se assemelhem a colunas data-at-execution, o valor devolvido pelo SQLParamData é diferente para cada um.
As colunas Data-at-execution são colunas num conjunto de linhas para as quais os dados serão enviados com SQLPutData quando uma linha é atualizada ou inserida com SQLBulkOperations. Estão vinculados ao SQLBindCol. O valor devolvido pelo SQLParamData é o endereço da linha no buffer *TargetValuePtr que está a ser processada.
A aplicação chama SQLPutData uma ou mais vezes para enviar dados para a coluna. É necessária mais do que uma chamada se todo o valor dos dados não puder ser devolvido no buffer *TargetValuePtr especificado em SQLPutData; múltiplas chamadas ao SQLPutData para a mesma coluna são permitidas apenas quando se envia dados de caracteres C para uma coluna com um tipo de dado específico de caracteres, binários ou fontes de dados, ou quando se envia dados binários C para uma coluna com um tipo de dado específico de carácter, binário ou fonte de dados.
A aplicação chama novamente o SQLParamData para sinalizar que todos os dados foram enviados para a coluna.
Se houver mais colunas de dados na execução, o SQLParamData devolve SQL_NEED_DATA e o endereço do buffer TargetValuePtr para a próxima coluna de dados na execução a ser processada. A candidatura repete os passos 4 e 5.
Se não existirem mais colunas de dados na execução, o processo está concluído. Se a instrução for executada com sucesso, o SQLParamData devolve SQL_SUCCESS ou SQL_SUCCESS_WITH_INFO; Se a execução falhar, devolve SQL_ERROR. Neste ponto, o SQLParamData pode devolver qualquer SQLSTATE que possa ser devolvido pelo SQLBulkOperations.
Se a operação for cancelada ou ocorrer um erro no SQLParamData ou SQLPutData após o retorno do SQLBulkOperations SQL_NEED_DATA e antes de os dados serem enviados para todas as colunas de dados na execução, a aplicação pode chamar apenas SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData ou SQLPutData para a instrução ou a ligação associada à declaração. Se chamar qualquer outra função para a instrução ou a ligação associada à instrução, a função retorna SQL_ERROR e SQLSTATE HY010 (erro de sequência de funções).
Se a aplicação chamar SQLCancel enquanto o driver ainda precisa de dados para as colunas de dados na execução, o driver cancela a operação. A aplicação pode então chamar novamente SQLBulkOperations ; cancelar não afeta o estado do cursor nem a posição atual do cursor.
Matriz de estado da linha
O array de estado de linhas contém valores de estado para cada linha de dados no conjunto de linhas após uma chamada ao SQLBulkOperations. O driver define os valores de estado neste array após uma chamada para SQLFetch, SQLFetchScroll, SQLSetPos ou SQLBulkOperations. Este array é inicialmente preenchido por uma chamada para SQLBulkOperations se SQLFetch ou SQLFetchScroll não tiver sido chamado antes de SQLBulkOperations. Este array é apontado pelo atributo da instrução SQL_ATTR_ROW_STATUS_PTR. O número de elementos nos arrays de estado de linhas deve ser igual ao número de linhas no conjunto de linhas (conforme definido pelo atributo de instrução SQL_ATTR_ROW_ARRAY_SIZE). Para informações sobre este array de estado de linhas, veja SQLFetch.
Exemplo de código
O exemplo seguinte obtém 10 linhas de dados de cada vez a partir da tabela Clientes. Depois, solicita ao utilizador uma ação a tomar. Para reduzir o tráfego de rede, o buffer de exemplo atualiza, elimina e insere localmente nos arrays limitados, mas em deslocamentos para além dos dados do conjunto de linhas. Quando o utilizador escolhe enviar atualizações, eliminações e inserções para a fonte dos dados, o código define o offset de ligação adequadamente e chama SQLBulkOperations. Para simplificar, o utilizador não pode armazenar mais de 10 atualizações, eliminações ou inserções.
// SQLBulkOperations_Function.cpp
// compile with: ODBC32.lib
#include <windows.h>
#include <sqlext.h>
#include "stdio.h"
#define UPDATE_ROW 100
#define DELETE_ROW 101
#define ADD_ROW 102
#define SEND_TO_DATA_SOURCE 103
#define UPDATE_OFFSET 10
#define INSERT_OFFSET 20
#define DELETE_OFFSET 30
// Define structure for customer data (assume 10 byte maximum bookmark size).
typedef struct tagCustStruct {
SQLCHAR Bookmark[10];
SQLINTEGER BookmarkLen;
SQLUINTEGER CustomerID;
SQLINTEGER CustIDInd;
SQLCHAR CompanyName[51];
SQLINTEGER NameLenOrInd;
SQLCHAR Address[51];
SQLINTEGER AddressLenOrInd;
SQLCHAR Phone[11];
SQLINTEGER PhoneLenOrInd;
} CustStruct;
// Allocate 40 of these structures. Elements 0-9 are for the current rowset,
// elements 10-19 are for the buffered updates, elements 20-29 are for
// the buffered inserts, and elements 30-39 are for the buffered deletes.
CustStruct CustArray[40];
SQLUSMALLINT RowStatusArray[10], Action, RowNum, NumUpdates = 0, NumInserts = 0,
NumDeletes = 0;
SQLLEN BindOffset = 0;
SQLRETURN retcode;
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLHSTMT hstmt = NULL;
int main() {
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLConnect(hdbc, (SQLCHAR*) "Northwind", SQL_NTS, (SQLCHAR*) NULL, 0, NULL, 0);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Set the following statement attributes:
// SQL_ATTR_CURSOR_TYPE: Keyset-driven
// SQL_ATTR_ROW_BIND_TYPE: Row-wise
// SQL_ATTR_ROW_ARRAY_SIZE: 10
// SQL_ATTR_USE_BOOKMARKS: Use variable-length bookmarks
// SQL_ATTR_ROW_STATUS_PTR: Points to RowStatusArray
// SQL_ATTR_ROW_BIND_OFFSET_PTR: Points to BindOffset
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(CustStruct), 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER)SQL_UB_VARIABLE, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_OFFSET_PTR, &BindOffset, 0);
// Bind arrays to the bookmark, CustomerID, CompanyName, Address, and Phone columns.
retcode = SQLBindCol(hstmt, 0, SQL_C_VARBOOKMARK, CustArray[0].Bookmark, sizeof(CustArray[0].Bookmark), &CustArray[0].BookmarkLen);
retcode = SQLBindCol(hstmt, 1, SQL_C_ULONG, &CustArray[0].CustomerID, 0, &CustArray[0].CustIDInd);
retcode = SQLBindCol(hstmt, 2, SQL_C_CHAR, CustArray[0].CompanyName, sizeof(CustArray[0].CompanyName), &CustArray[0].NameLenOrInd);
retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, CustArray[0].Address, sizeof(CustArray[0].Address), &CustArray[0].AddressLenOrInd);
retcode = SQLBindCol(hstmt, 4, SQL_C_CHAR, CustArray[0].Phone, sizeof(CustArray[0].Phone), &CustArray[0].PhoneLenOrInd);
// Execute a statement to retrieve rows from the Customers table.
retcode = SQLExecDirect(hstmt, (SQLCHAR*)"SELECT CustomerID, CompanyName, Address, Phone FROM Customers", SQL_NTS);
// Fetch and display the first 10 rows.
retcode = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0);
// DisplayCustData(CustArray, 10);
// Call GetAction to get an action and a row number from the user.
// while (GetAction(&Action, &RowNum)) {
Action = SQL_FETCH_NEXT;
RowNum = 2;
switch (Action) {
case SQL_FETCH_NEXT:
case SQL_FETCH_PRIOR:
case SQL_FETCH_FIRST:
case SQL_FETCH_LAST:
case SQL_FETCH_ABSOLUTE:
case SQL_FETCH_RELATIVE:
// Fetch and display the requested data.
SQLFetchScroll(hstmt, Action, RowNum);
// DisplayCustData(CustArray, 10);
break;
case UPDATE_ROW:
// Check if we have reached the maximum number of buffered updates.
if (NumUpdates < 10) {
// Get the new customer data and place it in the next available element of
// the buffered updates section of CustArray, copy the bookmark of the row
// being updated to the same element, and increment the update counter.
// Checking to see we have not already buffered an update for this
// row not shown.
// GetNewCustData(CustArray, UPDATE_OFFSET + NumUpdates);
memcpy(CustArray[UPDATE_OFFSET + NumUpdates].Bookmark,
CustArray[RowNum - 1].Bookmark,
CustArray[RowNum - 1].BookmarkLen);
CustArray[UPDATE_OFFSET + NumUpdates].BookmarkLen =
CustArray[RowNum - 1].BookmarkLen;
NumUpdates++;
} else {
printf("Buffers full. Send buffered changes to the data source.");
}
break;
case DELETE_ROW:
// Check if we have reached the maximum number of buffered deletes.
if (NumDeletes < 10) {
// Copy the bookmark of the row being deleted to the next available element
// of the buffered deletes section of CustArray and increment the delete
// counter. Checking to see we have not already buffered an update for
// this row not shown.
memcpy(CustArray[DELETE_OFFSET + NumDeletes].Bookmark,
CustArray[RowNum - 1].Bookmark,
CustArray[RowNum - 1].BookmarkLen);
CustArray[DELETE_OFFSET + NumDeletes].BookmarkLen =
CustArray[RowNum - 1].BookmarkLen;
NumDeletes++;
} else
printf("Buffers full. Send buffered changes to the data source.");
break;
case ADD_ROW:
// reached maximum number of buffered inserts?
if (NumInserts < 10) {
// Get the new customer data and place it in the next available element of
// the buffered inserts section of CustArray and increment insert counter.
// GetNewCustData(CustArray, INSERT_OFFSET + NumInserts);
NumInserts++;
} else
printf("Buffers full. Send buffered changes to the data source.");
break;
case SEND_TO_DATA_SOURCE:
// If there are any buffered updates, inserts, or deletes, set the array size
// to that number, set the binding offset to use the data in the buffered
// update, insert, or delete part of CustArray, and call SQLBulkOperations to
// do the updates, inserts, or deletes. Because we will never have more than
// 10 updates, inserts, or deletes, we can use the same row status array.
if (NumUpdates) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumUpdates, 0);
BindOffset = UPDATE_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_UPDATE_BY_BOOKMARK);
NumUpdates = 0;
}
if (NumInserts) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumInserts, 0);
BindOffset = INSERT_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_ADD);
NumInserts = 0;
}
if (NumDeletes) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumDeletes, 0);
BindOffset = DELETE_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_DELETE_BY_BOOKMARK);
NumDeletes = 0;
}
// If there were any updates, inserts, or deletes, reset the binding offset
// and array size to their original values.
if (NumUpdates || NumInserts || NumDeletes) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);
BindOffset = 0;
}
break;
}
// }
// Close the cursor.
SQLFreeStmt(hstmt, SQL_CLOSE);
}
Funções relacionadas
| Para obter informações sobre | Veja |
|---|---|
| Ligar um buffer a uma coluna num conjunto de resultados | Função SQLBindCol |
| Cancelamento do processamento de extratos | Função SQLCancel |
| Buscar um bloco de dados ou percorrer um conjunto de resultados | Função SQLFetchScroll |
| Obter um único campo de um descritor | Função SQLGetDescField |
| Obter múltiplos campos de um descritor | Função SQLGetDescRec |
| Definir um único campo de um descritor | Função SQLSetDescField |
| Definir múltiplos campos de um descritor | Função SQLSetDescRec |
| Posicionar o cursor, atualizar dados no conjunto de linhas ou atualizar ou eliminar dados no conjunto de linhas | Função SQLSetPos |
| Definir um atributo de instrução | Função SQLSetStmtAttr |