Função SQLBulkOperations

Conformidade
Versão Introduzida: Conformidade com os Padrões ODBC 3.0: ODBC

Summary
O SQLBulkOperations realiza inserções em massa e operações de marcadores em massa, incluindo atualização, exclusão e busca por favorito.

Sintaxe

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

Argumentos

Identificador de declaração
[Entrada] Identificador de instrução.

Operação
[Entrada] Operação a realizar:

SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK

Para obter mais informações, consulte "Comentários".

Returns

SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR ou SQL_INVALID_HANDLE.

Diagnostics

Quando 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 a seguir lista os valores SQLSTATE normalmente retornados pelo SQLBulkOperations e explica cada um no contexto dessa função; a notação "(DM)" precede as descrições dos SQLSTATEs retornadas pelo Gerenciador de Drivers. O código de retorno associado a cada valor SQLSTATE é SQL_ERROR, a menos que indicado de outra forma.

Para todos aqueles SQLSTATEs que podem devolver SQL_SUCCESS_WITH_INFO ou SQL_ERROR (exceto 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO é retornado se ocorrer um erro em uma ou mais, mas não todas, linhas de uma operação multilinha, e SQL_ERROR é retornado se ocorrer um erro em uma operação de linha única.

SQLSTATE Erro DESCRIÇÃO
01000 Aviso geral Mensagem informativa específica do driver. (A função retorna SQL_SUCCESS_WITH_INFO.)
01004 Truncamento à direita dos dados da cadeia O argumento Operação era SQL_FETCH_BY_BOOKMARK, e dados em string ou binários retornados para uma coluna ou colunas com 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 na linha O argumento Operação estava SQL_ADD, e um erro ocorria em uma ou mais linhas durante a execução da operação, mas pelo menos uma linha foi adicionada com sucesso. (A função retorna SQL_SUCCESS_WITH_INFO.)

(Esse erro é gerado apenas quando uma aplicação está trabalhando com um ODBC 2. x driver.)
01S07 Truncamento fracionário 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 retornados aos buffers de aplicação para uma ou mais colunas eram truncados. (Para tipos de dados numéricos em C, a parte fracionária do número era truncada. Para tipos de dados de tempo, carimbo de tempo e intervalo C que contêm um componente de tempo, a porção fracionária do tempo foi truncada.)

(A função retorna SQL_SUCCESS_WITH_INFO.)
07006 Violação de atributo de tipo de dados 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 para SQLBindCol.

O argumento Operação era SQL_UPDATE_BY_BOOKMARK ou SQL_ADD, e o valor dos dados nos buffers de aplicação não podia ser convertido para o tipo de dado 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 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 discussão foi SQL_UPDATE_BY_BOOKMARK; e nenhuma coluna era atualizável porque todas as colunas eram não vinculadas ou somente 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 caractere 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 do conjunto de resultados fazia com que toda a parte (em oposição a fracionária) do número fosse truncada.

A Operação de argumento era SQL_FETCH_BY_BOOKMARK, e retornar o valor numérico de uma ou mais colunas limitadas causaria uma perda significativa de dígitos.
22007 Formato de data e 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 ano, mês ou dia ficasse fora do alcance.

A Operação de argumento era SQL_FETCH_BY_BOOKMARK, e retornar o valor de data ou hora de uma ou mais colunas vinculadas faria 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 o desempenho da aritmética de data-hora nos dados enviados para uma coluna do conjunto de resultados resultava em um campo de data-hora (ano, mês, dia, hora, minuto ou segundo campo) do resultado fora da faixa permitida de valores para o campo ou sendo inválido com base nas 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 recuperados do conjunto de resultados resultava em um campo de data-hora (ano, mês, dia, hora, minuto ou segundo campo) do resultado fora da faixa permitida de valores para o campo ou inválido com base nas regras naturais do calendário gregoriano para datas-horas.
22015 Estouro de campo de intervalo O argumento Operação era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK, e a atribuição de um tipo C numérico ou intervalo exato a um tipo de dado SQL de intervalo causava a perda de dígitos significativos.

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 Operação era SQL_FETCH_BY_BOOKMARK, e atribuir de um tipo SQL numérico ou intervaloso exato a um tipo C de intervalo causava a perda de dígitos significativos no campo inicial.

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 intervalo C.
22018 Valor de caractere inválido para especificação de conversão O argumento da Operação era SQL_FETCH_BY_BOOKMARK; o tipo C era um tipo numérico exato ou aproximado, um data-hora ou um tipo de dado de intervalo; o tipo SQL da coluna era um tipo de dado de caractere; e o valor na coluna não era um literal válido do tipo C limitado.

A Operação de argumentos era SQL_ADD ou SQL_UPDATE_BY_BOOKMARK; o tipo SQL era um tipo numérico exato ou aproximado, um tipo de 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ção 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 era 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 de cursor inválido O StatementHandle estava em estado executado, mas nenhum conjunto de resultados era associado ao StatementHandle.
40001 Falha de serialização A transação foi revertida devido a um deadlock de recursos com outra transação.
40003 Conclusão da instrução desconhecida A conexão associada falhou durante a execução dessa função e o estado da transação não pode ser determinado.
42000 Erro de sintaxe ou violação de acesso O driver não conseguiu travar a linha conforme necessário para realizar a operação solicitada no argumento Operação .
44000 Violação COM 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 em uma tabela visualizada (ou uma tabela derivada da tabela visualizada) criada especificando COM CHECK OPTION, de modo que uma ou mais linhas afetadas pelo insert ou atualização não estarão mais presentes na tabela visualizada.
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.
HY008 Operação cancelada O processamento assíncrono foi habilitado para o StatementHandle. A função foi chamada e, antes de concluir a execução, SQLCancel ou SQLCancelHandle foi chamado no StatementHandle. Em seguida, a função foi chamada novamente no StatementHandle.

A função foi chamada e, antes de concluir a execução, SQLCancel ou SQLCancelHandle foi chamado no StatementHandle de um thread diferente em um aplicativo multithread.
HY010 Erro de sequência de função (DM) Uma função de execução assíncrona foi chamada para o identificador de conexão associado ao StatementHandle. Essa função assíncrona ainda estava em execução quando a função SQLBulkOperations foi chamada.

(DM) SQLExecute, SQLExecDirect ou SQLMoreResults foi chamado para o StatementHandle e retornado SQL_PARAM_DATA_AVAILABLE. Essa função foi chamada antes que os dados fossem recuperados para todos os parâmetros transmitidos.

(DM) O StatementHandle especificado não estava em 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) foi chamada para o StatementHandle e ainda estava em execução quando essa função foi chamada.

(DM) SQLExecute, SQLExecDirect ou SQLSetPos era chamado para o HandleStatement e retornava 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) O motorista era um ODBC 2. x , e SQLBulkOperations era chamado para um StatementHandle antes de SQLFetchScroll ou SQLFetch serem chamados.

(DM) SQLBulkOperations foi chamado após o SQLExtendedFetch ser chamado no StatementHandle.
HY011 O atributo não pode ser definido agora (DM) O motorista 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 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.
HY090 Cadeia de caracteres ou comprimento de buffer inválido 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 dado C era SQL_C_BINARY ou SQL_C_CHAR; e o valor do comprimento da coluna era menor que 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 em um buffer de comprimento/indicador era SQL_DATA_AT_EXEC; o tipo SQL era SQL_LONGVARCHAR, SQL_LONGVARBINARY ou um tipo longo específico de fonte de dados; e o tipo de informação SQL_NEED_LONG_DATA_LEN 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 vinculada a um buffer cujo comprimento não era igual ao comprimento máximo do marcador para esse conjunto de resultados. (Esse 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 Operação era SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK ou SQL_UPDATE_BY_BOOKMARK, e a coluna de favoritos não era encadernada ou o atributo SQL_ATTR_USE_BOOKMARKS da instrução era definido como SQL_UB_OFF.
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.
HYC00 Recurso opcional não implementado O driver ou fonte de dados não suporta a operação solicitada no argumento Operação .
HYT00 Tempo limite expirado O período de tempo limite da consulta expirou antes que a fonte de dados retornasse o conjunto de resultados. O período de tempo é definido através do SQLSetStmtAttr com um argumento de Atributo de SQL_ATTR_QUERY_TIMEOUT.
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 StatementHandle não dá suporte à função.
IM017 A sondagem está desabilitada no modo de notificação assíncrona Sempre que o modelo de notificação é usado, a sondagem é desabilitada.
IM018 SQLCompleteAsync não foi chamado para concluir a operação assíncrona anterior nesse identificador. Se a chamada de função anterior no identificador retornar SQL_STILL_EXECUTING e se o modo de notificação estiver habilitado, SQLCompleteAsync deverá ser chamado no identificador para fazer o pós-processamento e concluir a operação.

Comments

Caution

Para informações sobre quais estados de instrução SQLBulkOperations pode ser chamado e o que ele deve fazer para compatibilidade com o ODBC 2. x , veja a seção Block Cursors, Scrollable Cursors, and Backward Compatibility no Apêndice G: Diretrizes de Driver para Retrocompatibilidade.

Uma aplicação utiliza SQLBulkOperations para realizar as seguintes operações na tabela base ou visualização que corresponde à consulta atual:

  • Adicione novas linhas.

  • Atualize um conjunto de linhas onde cada linha é identificada por um favorito.

  • Exclua um conjunto de linhas onde cada linha é identificada por um favorito.

  • Busque um conjunto de linhas onde cada linha é identificada por um favorito.

Após uma chamada para SQLBulkOperations, a posição do cursor de bloco permanece indefinida. A aplicação precisa 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 chama 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 para SQLBulkOperations ao definir o buffer de comprimento/indicador da coluna especificado na chamada para SQLBindCol para SQL_COLUMN_IGNORE.

Não é necessário que a aplicação defina o atributo da instrução SQL_ATTR_ROW_OPERATION_PTR ao chamar SQLBulkOperations porque as linhas não podem ser ignoradas ao realizar operações em massa com essa função.

O buffer apontado pelo atributo SQL_ATTR_ROWS_FETCHED_PTR da instrução 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 de uma referência à mesma coluna, ele é definido pelo driver se um erro é gerado ou se o driver ignora as referências duplicadas e executa as operações solicitadas.

Para mais informações sobre como usar SQLBulkOperations, veja Atualizando 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:

  1. Executa uma consulta que retorna um conjunto de resultados.

  2. Define o atributo da instrução SQL_ATTR_ROW_ARRAY_SIZE ao número de linhas que deseja inserir.

  3. Chama SQLBindCol para vincular os dados que deseja inserir. Os dados são vinculados a um array com tamanho igual ao valor de SQL_ATTR_ROW_ARRAY_SIZE.

    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.

  4. Chama SQLBulkOperations(StatementHandle, SQL_ADD) para realizar a inserção.

  5. Se a aplicação definiu o atributo SQL_ATTR_ROW_STATUS_PTR de instrução, ela pode inspecionar esse array para ver o resultado da operação.

Se uma aplicação vincular a coluna 0 antes de chamar SQLBulkOperations com um argumento Operation de SQL_ADD, o driver atualizará os buffers da coluna 0 vinculados com os valores de favoritos da linha recém-inserida. Para que isso aconteça, a aplicação deve ter definido o atributo SQL_ATTR_USE_BOOKMARKS da instrução como SQL_UB_VARIABLE antes de executar a instrução. (Isso não funciona com um ODBC 2. x driver.)

Dados longos podem ser adicionados em partes pelo SQLBulkOperations, usando chamadas para SQLParamData e SQLPutData. Para mais informações, veja "Fornecendo 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 está contra um ODBC 2.driver X ; veja Compatibilidade Retroativa e Conformidade de Normas).

O comportamento é definido pelo driver se SQLBulkOperations, com um argumento Operação de SQL_ADD, for chamado em um cursor que contenha colunas duplicadas. O driver pode retornar um SQLSTATE definido pelo driver, adicionar os dados à primeira coluna que aparece no conjunto de resultados ou executar outros comportamentos definidos pelo driver.

Realizando Atualizações em Massa Usando Marcadores de Favoritos

Para realizar atualizações em massa usando favoritos com SQLBulkOperations, uma aplicação executa os seguintes passos em sequência:

  1. Define o atributo da instrução SQL_ATTR_USE_BOOKMARKS para SQL_UB_VARIABLE.

  2. Executa uma consulta que retorna um conjunto de resultados.

  3. Define o atributo da SQL_ATTR_ROW_ARRAY_SIZE para o número de linhas que deseja atualizar.

  4. Chama o SQLBindCol para vincular os dados que deseja atualizar. Os dados são vinculados a um array com tamanho igual ao valor de SQL_ATTR_ROW_ARRAY_SIZE. Também chama o SQLBindCol para vincular a coluna 0 (a coluna de favoritos).

  5. Copia os favoritos das linhas que deseja atualizar no array vinculado à coluna 0.

  6. Atualiza os dados nos buffers vinculados.

    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.

  7. Chamadas de SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).

    Note

    Se a aplicação definiu o atributo SQL_ATTR_ROW_STATUS_PTR de instrução, ela pode inspecionar esse array para ver o resultado da operação.

  8. Opcionalmente, chama SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) para buscar dados nos buffers de aplicação vinculados e verificar se a atualização ocorreu.

  9. Se os dados foram atualizados, o driver altera o valor no array de status de linhas para que as linhas apropriadas SQL_ROW_UPDATED.

Atualizações em massa realizadas pelo SQLBulkOperations podem incluir dados longos usando chamadas para SQLParamData e SQLPutData. Para mais informações, veja "Fornecendo Dados Longos para Inserções e Atualizações em Massa" mais adiante nesta referência de função.

Se os favoritos persistirem entre os cursores, o aplicativo não precisa chamar SQLFetch ou SQLFetchScroll antes de atualizar pelos favoritos. Ele pode usar favoritos que armazenou de um cursor anterior. Se os favoritos não persistirem entre os cursores, o aplicativo precisa chamar SQLFetch ou SQLFetchScroll para recuperar os favoritos.

O comportamento é definido pelo driver se SQLBulkOperations, com um argumento Operação de SQL_UPDATE_BY_BOOKMARK, for chamado em um cursor que contenha colunas duplicadas. O driver pode retornar um SQLSTATE definido pelo driver, atualizar a primeira coluna que aparece no conjunto de resultados ou executar outros comportamentos definidos pelo driver.

Realizando buscas em massa usando marcadores de página

Para realizar buscas em massa usando bookmarks com SQLBulkOperations, uma aplicação executa os seguintes passos em sequência:

  1. Define o atributo da instrução SQL_ATTR_USE_BOOKMARKS para SQL_UB_VARIABLE.

  2. Executa uma consulta que retorna um conjunto de resultados.

  3. Define o atributo da instrução SQL_ATTR_ROW_ARRAY_SIZE ao número de linhas que deseja buscar.

  4. Chama SQLBindCol para vincular os dados que deseja buscar. Os dados são vinculados a um array com tamanho igual ao valor de SQL_ATTR_ROW_ARRAY_SIZE. Também chama o SQLBindCol para vincular a coluna 0 (a coluna de favoritos).

  5. Copia os favoritos das linhas que ele tem interesse em buscar no array vinculado à coluna 0. (Isso pressupõe que a aplicação já tenha obtido os marcadores separadamente.)

    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.

  6. Chama SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK).

  7. Se a aplicação definiu o atributo SQL_ATTR_ROW_STATUS_PTR de instrução, ela pode inspecionar esse array para ver o resultado da operação.

Se os marcadores persistirem entre os cursores, o aplicativo não precisa chamar SQLFetch ou SQLFetchScroll antes de buscar os marcadores. Ele pode usar favoritos que armazenou de um cursor anterior. Se os favoritos não persistirem entre os cursores, a aplicação precisa chamar SQLFetch ou SQLFetchScroll uma vez para recuperar os favoritos.

Realizando Exclusõ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:

  1. Define o atributo da instrução SQL_ATTR_USE_BOOKMARKS para SQL_UB_VARIABLE.

  2. Executa uma consulta que retorna um conjunto de resultados.

  3. Define o atributo SQL_ATTR_ROW_ARRAY_SIZE de instrução ao número de linhas que deseja deletar.

  4. Chama SQLBindCol para vincular a coluna 0 (a coluna de favoritos).

  5. Copia os favoritos das linhas que deseja excluir no array vinculado à coluna 0.

    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.

  6. Chamadas SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK).

  7. Se a aplicação definiu o atributo SQL_ATTR_ROW_STATUS_PTR de instrução, ela pode inspecionar esse array para ver o resultado da operação.

Se os favoritos persistirem entre os cursores, o aplicativo não precisa chamar SQLFetch ou SQLFetchScroll antes de excluir pelos favoritos. Ele pode usar favoritos que armazenou de um cursor anterior. Se os favoritos não persistirem entre os cursores, a aplicação precisa chamar SQLFetch ou SQLFetchScroll uma vez para recuperar os favoritos.

Fornecimento de dados longos para inserções e atualizações em massa

Dados longos podem ser fornecidos 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 seções "Realização de Inserções em Massa" e "Realização de Atualizações em Massa Usando Favoritos" anteriormente neste tópico.

  1. 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 posteriormente 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 dado SQL da coluna for SQL_LONGVARBINARY, SQL_LONGVARCHAR ou um tipo longo específico de fonte de dados e o driver retorna "Y" para o tipo de informação SQL_NEED_LONG_DATA_LEN em SQLGetInfo, o comprimento é o número de bytes de dados a serem enviados para o parâmetro; caso contrário, deve ser um valor não negativo e é ignorado.

  2. Quando o SQLBulkOperations é chamado, se houver colunas de dados na execução, a função retorna SQL_NEED_DATA e prossegue para o passo 3, que se segue. (Se não houver colunas de dados na execução, o processo está completo.)

  3. 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 retorna SQL_NEED_DATA. A aplicação recupera o valor definido pela aplicação do buffer *TargetValuePtr .

    Note

    Embora os parâmetros de dados em execução sejam semelhantes a colunas de dados em execução, o valor retornado por SQLParamData é diferente para cada um.

    Colunas de dados na execução são colunas em um conjunto de linhas para as quais os dados serão enviados com SQLPutData quando uma linha for atualizada ou inserida com SQLBulkOperations. Eles estão associados a SQLBindCol. O valor retornado pelo SQLParamData é o endereço da linha no buffer *TargetValuePtr que está sendo processada.

  4. O aplicativo chama SQLPutData uma ou mais vezes para enviar dados para a coluna. Mais de uma chamada é necessária se todo o valor dos dados não puder ser retornado no buffer *TargetValuePtr especificado em SQLPutData; múltiplas chamadas para SQLPutData para a mesma coluna são permitidas apenas ao enviar dados de caracteres C para uma coluna com um tipo de dado específico de caractere, binário ou fonte de dados, ou ao enviar dados binários C para uma coluna com um tipo de dado específico de caractere, binário ou fonte de dados.

  5. O aplicativo chama novamente o SQLParamData para sinalizar que todos os dados foram enviados para a coluna.

    • Se houver mais colunas de dados na execução, SQLParamData retorna SQL_NEED_DATA e o endereço do buffer TargetValuePtr para a próxima coluna de dados na execução a ser processada. O aplicativo repete as etapas 4 e 5.

    • Se não houver mais colunas de dados na execução, o processo está completo. Se a instrução foi executada com sucesso, SQLParamData retorna SQL_SUCCESS ou SQL_SUCCESS_WITH_INFO; Se a execução falhar, ele retorna SQL_ERROR. Neste ponto, SQLParamData pode retornar qualquer estado SQLSTATE que possa ser retornado por SQLBulkOperations.

Se a operação for cancelada ou ocorrer um erro em SQLParamData ou SQLPutData após o retorno de 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 conexão associada à instrução. Se chamar qualquer outra função para a instrução ou a conexã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 SQLBulkOperations novamente; cancelar não afeta o estado do cursor nem a posição atual do cursor.

Matriz de status da linha

O array de status de linhas contém valores de status para cada linha de dados no conjunto de linhas após uma chamada para SQLBulkOperations. O driver define os valores de status nesse array após uma chamada para SQLFetch, SQLFetchScroll, SQLSetPos ou SQLBulkOperations. Esse array é inicialmente preenchido por uma chamada para SQLBulkOperations se SQLFetch ou SQLFetchScroll não foram chamados antes do SQLBulkOperations. Esse array é apontado pelo atributo SQL_ATTR_ROW_STATUS_PTR sentença. O número de elementos nos arrays de status de linhas deve ser igual ao número de linhas no conjunto de linhas (conforme definido pelo atributo SQL_ATTR_ROW_ARRAY_SIZE sentença). Para informações sobre esse array de status de linha, veja SQLFetch.

Exemplo de código

O exemplo a seguir obtém 10 linhas de dados por vez da tabela Clientes. Em seguida, ele solicita ao usuário uma ação a ser tomada. Para reduzir o tráfego de rede, o buffer de exemplo atualiza, exclui e insere localmente nos arrays limitados, mas em deslocamentos além dos dados do conjunto de linhas. Quando o usuário escolhe enviar atualizações, excluções e inserções para a fonte dos dados, o código define o offset de vinculação adequadamente e chama SQLBulkOperations. Para simplificar, o usuário não pode armazenar mais de 10 atualizações, excluçõ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);  
}  
Para obter informações sobre Veja
Associando um buffer a uma coluna em um conjunto de resultados Função SQLBindCol
Cancelando o processamento de instruções Função SQLCancel
Buscando um bloco de dados ou rolando por um conjunto de resultados Função SQLFetchScroll
Obtendo um único campo de um descritor Função SQLGetDescField
Obtendo múltiplos campos de um descritor Função SQLGetDescRec
Definindo um único campo de um descritor Função SQLSetDescField
Definindo múltiplos campos de um descritor Função SQLSetDescRec
Posicionamento do cursor, atualização dos dados no conjunto de linhas ou atualização ou exclusão de dados no conjunto Função SQLSetPos
Configurando um atributo de instrução Função SQLSetStmtAttr