Função SQLSetPos

Conformidade
Versão Introduzida: Conformidade com as Normas ODBC 1.0: ODBC

Summary
O SQLSetPos define a posição do cursor num conjunto de linhas e permite que uma aplicação atualize dados no conjunto de linhas ou atualize ou elimine dados do conjunto de resultados.

Syntax

  
SQLRETURN SQLSetPos(  
      SQLHSTMT        StatementHandle,  
      SQLSETPOSIROW   RowNumber,  
      SQLUSMALLINT    Operation,  
      SQLUSMALLINT    LockType);  

Arguments

HandleStatement
[Entrada] Identificador do extrato.

Número de Linha
[Entrada] Posição da linha no conjunto de linhas sobre a qual realizar a operação especificada com o argumento Operação . Se RowNumber for 0, a operação aplica-se a todas as linhas do conjunto de linhas.

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

Funcionamento
[Entrada] Operação a realizar:

SQL_POSITION SQL_REFRESH SQL_UPDATE SQL_DELETE

Note

O valor SQL_ADD para o argumento Operação foi descontinuado para o ODBC 3.x. Os drivers ODBC 3.x terão de suportar SQL_ADD para compatibilidade retroativa. Esta funcionalidade foi substituída por uma chamada para SQLBulkOperations com uma Operação de SQL_ADD. Quando uma aplicação ODBC 3.x funciona com um driver ODBC 2.x , o Gestor de Drivers mapeia uma chamada para SQLBulkOperations com uma Operação de SQL_ADD para SQLSetPos com uma Operação de SQL_ADD.

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

LockType
[Entrada] Especifica como bloquear a linha após a execução da operação especificada no argumento Operação .

SQL_LOCK_NO_CHANGE SQL_LOCK_EXCLUSIVE SQL_LOCK_UNLOCK

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 SQLSetPos devolve SQL_ERROR ou SQL_SUCCESS_WITH_INFO, pode ser obtido um valor SQLSTATE associado chamando SQLGetDiagRec com um HandleType de SQL_HANDLE_STMT e um Handle de StatementHandle. A tabela seguinte lista os valores SQLSTATE comumente devolvidos pelo SQLSetPos 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.)
01001 Conflito de operação de cursor O argumento da Operação era SQL_DELETE ou SQL_UPDATE, e nenhuma linha ou mais do que uma linha era eliminada ou atualizada. (Para mais informações sobre atualizações em mais do que uma linha, veja a descrição do Atributo SQL_ATTR_SIMULATE_CURSOR em SQLSetStmtAttr.) (Função devolve SQL_SUCCESS_WITH_INFO.)

O argumento da Operação era SQL_DELETE ou SQL_UPDATE, e a operação falhou devido à concorrência otimista. (Função devolve SQL_SUCCESS_WITH_INFO.)
01004 Truncamento à direita dos dados da cadeia O argumento Operação era SQL_REFRESH, 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 RowNumber era 0, e ocorria um erro numa ou mais linhas durante a execução da operação especificada com o argumento Operation .

(SQL_SUCCESS_WITH_INFO é devolvido se ocorrer um erro numa ou mais, mas não em todas, linhas de uma operação multilinha, e SQL_ERROR é devolvido se ocorrer um erro numa operação de uma única linha.)

(Este SQLSTATE é devolvido apenas quando SQLSetPos é chamado após SQLExtendedFetch, se o driver for um driver ODBC 2.x e a biblioteca de cursores não for utilizada.)
01S07 Truncamento fracionado O argumento Operação era SQL_REFRESH, 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 tipos de dados numéricos, a parte fracionária do número era truncada. Para tipos de dados de tempo, carimbo temporal e intervalo contendo um componente temporal, a parte fracionária do tempo foi truncada.

(Função devolve SQL_SUCCESS_WITH_INFO.)
07006 Violação de atributo de tipo de dado restrito O valor de dados de uma coluna no conjunto de resultados não podia ser convertido para o tipo de dados especificado pelo TargetType na chamada ao SQLBindCol.
07009 Índice de descritores inválido A Operação de argumento era SQL_REFRESH ou SQL_UPDATE, 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 era SQL_UPDATE, e nenhuma coluna era atualizável porque todas as colunas eram ou não ligadas, apenas leitura, ou o valor no buffer de comprimento/indicador limitado era SQL_COLUMN_IGNORE.
22001 Dados de cadeia, truncagem à direita O argumento Operação era SQL_UPDATE, e a atribuição de um carácter ou valor binário a uma coluna 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 A Operação de argumento era SQL_UPDATE, e a atribuição de um valor numérico a uma coluna no conjunto de resultados fazia com que toda a parte (em oposição à fracionária) do número fosse truncada.

O argumento Operação era SQL_REFRESH, e devolver o valor numérico de uma ou mais colunas encadernadas teria causado uma perda significativa de dígitos.
22007 Formato de data-hora inválido A Operação de argumento era SQL_UPDATE, 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.

O argumento Operação era SQL_REFRESH, e devolver o valor de data ou hora de uma ou mais colunas encadernadas faria com que o campo do ano, mês ou dia ficasse fora do alcance.
22008 Excedente de campo data/hora O argumento da Operação era SQL_UPDATE, e a execução da aritmética data-hora nos dados enviados para uma coluna do conjunto de resultados resultava num campo data-hora (o ano, mês, dia, hora, minuto ou segundo campo) em que o resultado ficava fora do intervalo permitido de valores para o campo, ou era inválido segundo as regras naturais do calendário gregoriano para datas-horas.

O argumento da Operação era SQL_REFRESH, e o desempenho da aritmética de data-hora nos dados recuperados do conjunto de resultados resultava num campo de data-hora (o ano, mês, dia, hora, minuto ou segundo campo) em que o resultado ficava fora do intervalo permitido de valores para o campo, ou era inválido segundo as regras naturais do calendário gregoriano para datas-horas.
22015 Excesso de campo de intervalo O argumento Operação era SQL_UPDATE, e a atribuição de um tipo numérico exato ou de intervalo C a um tipo de dado SQL de intervalo causava uma perda significativa de dígitos.

O argumento da Operação era SQL_UPDATE; 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_REFRESH, e atribuir de um tipo SQL numérico ou de intervalo exato a um tipo C de intervalo causava uma perda significativa de dígitos no campo principal.

O argumento da Operação era SQL_ REFRESH; 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_REFRESH; 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 foi SQL_UPDATE; 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 Operação era SQL_DELETE ou SQL_UPDATE, e uma restrição de integridade era violada.
24000 Estado do cursor inválido O StatementHandle estava num estado executado, mas nenhum conjunto de resultados estava associado ao StatementHandle.

(DM) Um cursor estava aberto no HandleStatement, mas SQLFetch ou SQLFetchScroll não tinham sido chamados.

Um cursor estava aberto no HandleStatement, e SQLFetch ou SQLFetchScroll tinham sido chamados, mas o cursor era posicionado antes do início do conjunto de resultados ou depois do fim do conjunto.

A Operação de argumento era SQL_DELETE, SQL_REFRESH ou SQL_UPDATE, e o cursor era posicionado antes do início do conjunto de resultados ou depois do fim do conjunto.
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 maquinista não conseguiu bloquear a linha como necessário para realizar a operação solicitada no argumento Operação.

O condutor não conseguiu bloquear a fila conforme solicitado no argumento LockType.
44000 COM VIOLAÇÃO DA OPÇÃO DE VERIFICAÇÃO O argumento Operação era SQL_UPDATE, e a atualização era realizada numa tabela vista ou numa tabela derivada da tabela vista criada especificando COM CHECK OPTION, de modo que uma ou mais linhas afetadas pela 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, e depois a função era novamente chamada 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 SQLSetPos foi chamada.

(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, SQLBulkOperations ou SQLSetPos era chamado para o StatementHandle e devolvido 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 driver era um driver ODBC 2.x , e o SQLSetPos era chamado para um StatementHandle após o SQLFetch ser chamado.
HY011 O atributo não pode ser definido agora (DM) O driver era um driver ODBC 2.x ; o atributo de SQL_ATTR_ROW_STATUS_PTR foi definido; depois, SQLSetPos foi chamado antes de SQLFetch, SQLFetchScroll ou SQLExtendedFetch serem chamados.
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 Operação era SQL_UPDATE, um valor de dado era um ponteiro nulo, e o valor do comprimento da coluna não era 0, SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NULL_DATA, nem menor ou igual a SQL_LEN_DATA_AT_EXEC_OFFSET.

O argumento da Operação era SQL_UPDATE; 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".
HY092 Identificador de atributo inválido (DM) O valor especificado para o argumento Operação era inválido.

(DM) O valor especificado para o argumento LockType era inválido.

O argumento da Operação era SQL_UPDATE ou SQL_DELETE, e o atributo de SQL_ATTR_CONCURRENCY afirmação era SQL_ATTR_CONCUR_READ_ONLY.
HY107 Valor da linha fora do intervalo O valor especificado para o argumento RowNumber era maior do que o número de linhas no conjunto de linhas.
HY109 Posição inválida do cursor O cursor associado ao StatementHandle foi definido como apenas para frente, pelo que o cursor não podia ser posicionado dentro do conjunto de linhas. Veja a descrição do atributo SQL_ATTR_CURSOR_TYPE em SQLSetStmtAttr.

O argumento Operação era SQL_UPDATE, SQL_DELETE ou SQL_REFRESH, e a linha identificada pelo argumento RowNumber tinha sido eliminada ou não tinha sido recuperada.

(DM) O argumento RowNumber era 0, e o argumento Operação era SQL_POSITION.

SQLSetPos era chamado depois de ser chamado SQLBulkOperations e antes de SQLFetchScroll ou SQLFetch ser chamado.
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 Operation ou no argumento LockType .
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 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 a afirmação que o SQLSetPos pode ser chamado e o que precisa de fazer para a compatibilidade com aplicações ODBC 2.x , veja Block Cursors, Scrollable Cursors e Backward Compatibility.

Argumento RowNumber

O argumento RowNumber especifica o número da linha no conjunto de linhas sobre a qual realizar a operação especificada pelo argumento Operation . Se RowNumber for 0, a operação aplica-se a todas as linhas do conjunto de linhas. RowNumber deve ser um valor de 0 até ao número de linhas no conjunto de linhas.

Note

Na linguagem C, os arrays são baseados em 0 e o argumento RowNumber é baseado em 1. Por exemplo, para atualizar a quinta linha do conjunto de linhas, uma aplicação modifica os buffers do conjunto de linhas no índice do array 4, mas especifica um Número de Linha de 5.

Todas as operações posicionam o cursor na linha especificada por RowNumber. As seguintes operações requerem uma posição do cursor:

  • Posicionar instruções de atualização e eliminação.

  • Chamadas para SQLGetData.

  • Chamadas para SQLSetPos com as opções SQL_DELETE, SQL_REFRESH e SQL_UPDATE.

Por exemplo, se RowNumber for 2 para uma chamada ao SQLSetPos com uma Operação de SQL_DELETE, o cursor está posicionado na segunda linha do conjunto de linhas e essa linha é eliminada. A entrada no array de estado da linha de implementação (apontada pelo atributo da instrução SQL_ATTR_ROW_STATUS_PTR) para a segunda linha é alterada para SQL_ROW_DELETED.

Uma aplicação pode especificar a posição do cursor quando chama SQLSetPos. Geralmente, chama SQLSetPos com a operação SQL_POSITION ou SQL_REFRESH para posicionar o cursor antes de executar uma instrução de atualização ou delete posicionada ou chamar SQLGetData.

Argumento de Operação

O argumento Operação suporta as seguintes operações. Para determinar quais as opções suportadas por uma fonte de dados, uma aplicação chama SQLGetInfo com o tipo de informação SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 ou SQL_STATIC_CURSOR_ATTRIBUTES1 (dependendo do tipo do cursor).

Funcionamento

argumento
Operation
SQL_POSITION O condutor posiciona o cursor na fila especificada pelo RowNumber.

O conteúdo do array de estado de linhas apontado pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR é ignorado para a Operação SQL_POSITION.
SQL_REFRESH O driver posiciona o cursor na linha especificada pelo RowNumber e atualiza os dados nos buffers do conjunto de linhas dessa linha. Para mais informações sobre como o driver devolve dados nos buffers de linhas, consulte as descrições da ligação linha a linha e coluna a coluna no SQLBindCol.

O SQLSetPos com uma Operação de SQL_REFRESH atualiza o estado e o conteúdo das linhas dentro do conjunto de linhas atual obtido. Isto inclui a atualização dos marcadores. Como os dados nos buffers são atualizados mas não recolhidos, a pertença ao conjunto de linhas é fixa. Isto é diferente da atualização realizada por uma chamada ao SQLFetchScroll com um FetchOrientation de SQL_FETCH_RELATIVE e um RowNumber igual a 0, que recupera o conjunto de linhas do conjunto de resultados para que possa mostrar dados adicionados e remover dados eliminados se essas operações forem suportadas pelo driver e pelo cursor.

Uma atualização bem-sucedida com SQLSetPos não altera o estado de uma linha de SQL_ROW_DELETED. As linhas eliminadas dentro do conjunto de linhas continuarão a ser marcadas como eliminadas até à próxima busca. As linhas desaparecem na próxima busca se o cursor suportar o empacotamento (em que um SQLFetch ou SQLFetchScroll subsequente não devolve linhas eliminadas).

As linhas adicionadas não aparecem quando é realizada uma atualização com SQLSetPos. Este comportamento é diferente do SQLFetchScroll , com um FetchType de SQL_FETCH_RELATIVE e um RowNumber igual a 0, que também atualiza o conjunto de linhas atual, mas mostrará registos adicionados ou registos eliminados se estas operações forem suportadas pelo cursor.

Uma atualização bem-sucedida com SQLSetPos alterará o estado da linha de SQL_ROW_ADDED para SQL_ROW_SUCCESS (se o array de estado da linha existir).

Uma atualização bem-sucedida com SQLSetPos altera o estado da linha de SQL_ROW_UPDATED para o novo estado da linha (se o array de estado da linha existir).

Se ocorrer um erro numa operação SQLSetPos numa linha, o estado da linha é definido para SQL_ROW_ERROR (se o array de estado de linha existir).

Para um cursor aberto com um atributo SQL_ATTR_CONCURRENCY de instrução de SQL_CONCUR_ROWVER ou SQL_CONCUR_VALUES, uma atualização com SQLSetPos pode atualizar os valores otimistas de concorrência usados pela fonte de dados para detetar que a linha mudou. Se isto ocorrer, as versões de linhas ou valores usados para garantir a concorrência do cursor são atualizados sempre que os buffers do conjunto de linhas são atualizados a partir do servidor. Isto acontece para cada linha que é atualizada.

O conteúdo do array de estado da linha apontado pelo atributo da instrução SQL_ATTR_ROW_OPERATION_PTR é ignorado para a Operação SQL_REFRESH.
SQL_UPDATE O driver posiciona o cursor na linha especificada pelo RowNumber e atualiza a linha subjacente de dados com os valores nos buffers do conjunto de linhas (o argumento TargetValuePtr no SQLBindCol). Recupera os comprimentos dos dados dos buffers de comprimento/indicador (o argumento StrLen_or_IndPtr no SQLBindCol). Se o comprimento de qualquer coluna for SQL_COLUMN_IGNORE, a coluna não é atualizada. Após atualizar a linha, o driver altera o elemento correspondente do array de estado da linha para SQL_ROW_UPDATED ou SQL_ROW_SUCCESS_WITH_INFO (se o array de estado da linha existir).

É definido pelo driver qual é o comportamento se o SQLSetPos com um argumento Operation de SQL_UPDATE for chamado num cursor que contenha colunas duplicadas. O driver pode devolver um SQLSTATE definido pelo driver, pode atualizar a primeira coluna que aparece no conjunto de resultados, ou executar outros comportamentos definidos pelo driver.

O array de operações de linhas apontado pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR pode ser usado para indicar que uma linha no conjunto de linhas atual deve ser ignorada durante uma atualização em massa. Para mais informações, veja "Arrays de Estado e Operações" mais adiante nesta referência de função.
SQL_DELETE O driver posiciona o cursor na linha especificada pelo RowNumber e elimina a linha subjacente de dados. Altera o elemento correspondente do array de estado da linha para SQL_ROW_DELETED. Depois de a linha ter sido eliminada, os seguintes não são válidos para a linha: instruções de atualização e exclusão posicionadas, chamadas para SQLGetData e chamadas para SQLSetPos com Operação definida para qualquer coisa exceto SQL_POSITION. Para drivers que suportam empacotamento, a linha é eliminada do cursor quando novos dados são recuperados da fonte de dados.

Se a linha permanece visível depende do tipo de cursor. Por exemplo, linhas eliminadas são visíveis para cursores estáticos e controlados por keysets, mas invisíveis para cursores dinâmicos.

O array de operações de linhas apontado pelo atributo da instrução SQL_ATTR_ROW_OPERATION_PTR pode ser usado para indicar que uma linha no conjunto de linhas atual deve ser ignorada durante uma eliminação em massa. Para mais informações, veja "Arrays de Estado e Operações" mais adiante nesta referência de função.

Argumento LockType

O argumento LockType fornece uma forma para as aplicações controlarem a concorrência. Na maioria dos casos, fontes de dados que suportam níveis e transações de concorrência suportarão apenas o valor SQL_LOCK_NO_CHANGE do argumento LockType . O argumento LockType é geralmente usado apenas para suporte baseado em ficheiros.

O argumento LockType especifica o estado de bloqueio da linha após a execução do SQLSetPos . Se o driver não conseguir bloquear a linha para realizar a operação solicitada ou para satisfazer o argumento LockType , devolve SQL_ERROR e SQLSTATE 42000 (erro de sintaxe ou violação de acesso).

Embora o argumento LockType seja especificado para uma única sentença, o bloqueio concede os mesmos privilégios a todas as instruções na ligação. Em particular, um bloqueio adquirido por uma instrução numa ligação pode ser desbloqueado por uma instrução diferente na mesma ligação.

Uma linha bloqueada através do SQLSetPos permanece bloqueada até que a aplicação chame SQLSetPos para a linha com LockType definido para SQL_LOCK_UNLOCK, ou até que a aplicação chame SQLFreeHandle para a instrução ou SQLFreeStmt com a opção SQL_CLOSE. Para um driver que suporta transações, uma linha bloqueada através do SQLSetPos é desbloqueada quando a aplicação chama o SQLEndTran para comprometer ou reverter uma transação na ligação (se um cursor for fechado quando uma transação é comprometida ou revertida, conforme indicado pelos tipos de informação SQL_CURSOR_COMMIT_BEHAVIOR e SQL_CURSOR_ROLLBACK_BEHAVIOR devolvidos pelo SQLGetInfo).

O argumento LockType suporta os seguintes tipos de fechaduras. Para determinar quais os bloqueios suportados por uma fonte de dados, uma aplicação chama SQLGetInfo com o tipo de informação SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 ou SQL_STATIC_CURSOR_ATTRIBUTES1 (dependendo do tipo do cursor).

Argumento do LockType Tipo de cadeado
SQL_LOCK_NO_CHANGE O driver ou fonte de dados garante que a linha está no mesmo estado bloqueado ou desbloqueado que estava antes de ser chamado o SQLSetPos . Este valor de LockType permite que fontes de dados que não suportam bloqueio explícito ao nível de linha utilizem qualquer bloqueio exigido pelos níveis atuais de concorrência e isolamento de transações.
SQL_LOCK_EXCLUSIVE O driver ou fonte de dados bloqueia a linha exclusivamente. Uma instrução numa ligação diferente ou numa aplicação diferente não pode ser usada para adquirir bloqueios na linha.
SQL_LOCK_UNLOCK O driver ou fonte de dados desbloqueia a linha.

Se um driver suportar SQL_LOCK_EXCLUSIVE mas não suportar SQL_LOCK_UNLOCK, uma linha bloqueada permanecerá bloqueada até que uma das chamadas de função descritas no parágrafo anterior ocorra.

Se um driver suportar SQL_LOCK_EXCLUSIVE mas não suportar SQL_LOCK_UNLOCK, uma linha bloqueada permanecerá bloqueada até que a aplicação chame SQLFreeHandle para a instrução ou SQLFreeStmt com a opção SQL_CLOSE. Se o driver suportar transações e fechar o cursor ao confirmar ou reverter a transação, a aplicação chama SQLEndTran.

Para as operações de atualização e eliminação no SQLSetPos, a aplicação utiliza o argumento LockType da seguinte forma:

  • Para garantir que uma linha não muda após ser recuperada, uma aplicação chama SQLSetPos com Operation definido para SQL_REFRESH e LockType para SQL_LOCK_EXCLUSIVE.

  • Se a aplicação definir o LockType para SQL_LOCK_NO_CHANGE, o driver garante que uma operação de atualização ou eliminação só terá sucesso se a aplicação especificar SQL_CONCUR_LOCK para o atributo da instrução SQL_ATTR_CONCURRENCY.

  • Se a aplicação especificar SQL_CONCUR_ROWVER ou SQL_CONCUR_VALUES para o atributo da instrução SQL_ATTR_CONCURRENCY, o controlador compara versões ou valores da linha e rejeita a operação se a linha tiver mudado desde que a aplicação a obteve para ela.

  • Se a aplicação especificar SQL_CONCUR_READ_ONLY para o atributo da instrução SQL_ATTR_CONCURRENCY, o driver rejeita qualquer operação de atualização ou eliminação.

Para mais informações sobre o atributo da instrução SQL_ATTR_CONCURRENCY, veja SQLSetStmtAttr.

Estado e Operação Arrays

Os seguintes arrays de estado e operações são usados ao chamar SQLSetPos:

  • O array de estado de linhas (apontado pelo campo SQL_DESC_ARRAY_STATUS_PTR no IRD e pelo atributo da instrução SQL_ATTR_ROW_STATUS_ARRAY) contém valores de estado para cada linha de dados no conjunto de linhas. O driver define os valores de estado neste array após uma chamada a SQLFetch, SQLFetchScroll, SQLBulkOperations ou SQLSetPos. Este array é apontado pelo atributo da instrução SQL_ATTR_ROW_STATUS_PTR.

  • O array de operações de linhas (apontado pelo campo SQL_DESC_ARRAY_STATUS_PTR no ARD e pelo atributo da instrução SQL_ATTR_ROW_OPERATION_ARRAY) contém um valor para cada linha do conjunto de linhas que indica se uma chamada ao SQLSetPos para uma operação em massa é ignorada ou realizada. Cada elemento do array é definido como SQL_ROW_PROCEED (o padrão) ou SQL_ROW_IGNORE. Este array é apontado pelo atributo da instrução SQL_ATTR_ROW_OPERATION_PTR.

O número de elementos nos arrays de estado e operação 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 o array de estado de linhas, consulte SQLFetch. Para informações sobre o array de operações de linhas, veja "Ignorar uma linha numa operação em massa", mais adiante nesta secção.

Utilização do SQLSetPos

Antes de uma aplicação chamar SQLSetPos, deve executar a seguinte sequência de passos:

  1. Se a aplicação chamar SQLSetPos com Operação definida para SQL_UPDATE, chame SQLBindCol (ou SQLSetDescRec) para cada coluna para especificar o seu tipo de dado e ligar buffers para os dados e comprimento da coluna.

  2. Se a aplicação chamar SQLSetPos com Operation definido em SQL_DELETE ou SQL_UPDATE, chame SQLColAttribute para garantir que as colunas a eliminar ou atualizar são atualizáveis.

  3. Chame SQLExecDirect, SQLExecute ou uma função de catálogo para criar um conjunto de resultados.

  4. Chame SQLFetch ou SQLFetchScroll para recuperar os dados.

Para mais informações sobre o uso do SQLSetPos, consulte Atualizar Dados com SQLSetPos.

Eliminar Dados Usando SQLSetPos

Para eliminar dados com SQLSetPos, uma aplicação chama SQLSetPos com RowNumber definido para o número da linha a eliminar e Operation definido para SQL_DELETE.

Depois de os dados terem sido eliminados, o driver altera o valor no array de estado da linha de implementação para a linha apropriada a SQL_ROW_DELETED (ou SQL_ROW_ERROR).

Atualização de Dados Usando SQLSetPos

Uma aplicação pode passar o valor de uma coluna quer no buffer de dados limitado, quer com uma ou mais chamadas ao SQLPutData. Colunas cujos dados são passados com SQLPutData são conhecidas como colunas data-at-execution. Estas são frequentemente usadas para enviar dados de colunas SQL_LONGVARBINARY e SQL_LONGVARCHAR e podem ser misturadas com outras colunas.

Para atualizar dados com SQLSetPos, uma aplicação:

  1. Coloca valores nos buffers de dados e comprimento/indicador vinculados com SQLBindCol:

    • Para colunas normais, a aplicação coloca o novo valor da coluna no buffer *TargetValuePtr e o comprimento desse valor no buffer *StrLen_or_IndPtr . Se a linha não for atualizada, a aplicação coloca SQL_ROW_IGNORE no elemento dessa linha do array de operações de linha.

    • Para colunas data-at-execution, a aplicação coloca um valor definido pela aplicação, como o número da coluna, no buffer *TargetValuePtr . 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.

  2. Chama SQLSetPos com o argumento Operação definido para SQL_UPDATE para atualizar a linha de dados.

    • Se não existirem colunas de dados na execução, o processo está completo.

    • Se existirem colunas de dados na execução, a função devolve SQL_NEED_DATA e avança para o passo 3.

  3. 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 de dados na execução sejam semelhantes às colunas de dados na execução, o valor devolvido pelo SQLParamData é diferente para cada um.

    Note

    Os parâmetros de dados na execução são parâmetros numa instrução SQL para os quais os dados serão enviados com SQLPutData quando a instrução é executada com SQLExecDirect ou SQLExecute. São vinculados com SQLBindParameter ou definindo descritores com SQLSetDescRec. O valor devolvido pelo SQLParamData é um valor de 32 bits passado para SQLBindParameter no argumento ParameterValuePtr .

    Note

    Colunas de dados na execução são colunas num conjunto de linhas para as quais os dados serão enviados com SQLPutData quando uma linha é atualizada com SQLSetPos. Estão vinculados ao SQLBindCol. O valor devolvido pelo SQLParamData é o endereço da linha no buffer *TargetValuePtr que está a ser processada.

  4. Liga ao SQLPutData uma ou mais vezes para enviar dados para a coluna. É necessária mais do que uma chamada se todos os valores de dados não puderem ser devolvidos 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.

  5. 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 estado SQLS que possa ser devolvido pelo SQLSetPos.

Se os dados forem atualizados, o driver altera o valor no array de estado das linhas de implementação para a linha apropriada a SQL_ROW_UPDATED.

Se a operação for cancelada ou ocorrer um erro em SQLParamData ou SQLPutData, após o SQLSetPos devolver 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 à instruçã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 SQLSetPos ; cancelar não afeta o estado do cursor nem a posição atual do cursor.

Quando a lista SELECT da especificação de consulta associada ao cursor contém mais do que uma referência à mesma coluna, se é gerado um erro ou se o driver ignora as referências duplicadas e executa as operações solicitadas, isso é definido pelo driver.

Realização de Operações em Grande Escala

Se o argumento RowNumber for 0, o driver executa a operação especificada no argumento Operation para cada linha do conjunto de linhas que tenha um valor de SQL_ROW_PROCEED no seu campo no array de operações de linha apontado por SQL_ATTR_ROW_OPERATION_PTR atributo de instrução. Este é um valor válido do argumento RowNumber para um argumento de Operação de SQL_DELETE, SQL_REFRESH ou SQL_UPDATE, mas não SQL_POSITION. SQLSetPos com uma Operação de SQL_POSITION e um Número de Linha igual a 0 devolverá SQLSTATE HY109 (Posição inválida do cursor).

Se ocorrer um erro relacionado com todo o conjunto de linhas, como SQLSTATE HYT00 (Timeout expired), o driver devolve SQL_ERROR e o SQLSTATE apropriado. O conteúdo dos buffers de linhas é indefinido e a posição do cursor mantém-se inalterada.

Se ocorrer um erro relacionado com uma única linha, o driver:

  • Define o elemento da linha no array de estado da linha apontado pelo atributo da instrução SQL_ATTR_ROW_STATUS_PTR como SQL_ROW_ERROR.

  • Publica um ou mais SQLSTATES adicionais para o erro na fila de erros e define o campo SQL_DIAG_ROW_NUMBER na estrutura de dados de diagnóstico.

Depois de processar o erro ou aviso, se o driver concluir a operação para as linhas restantes do conjunto de linhas, devolve SQL_SUCCESS_WITH_INFO. Assim, para cada linha que devolve um erro, a fila de erro contém zero ou mais SQLSTATEs adicionais. Se o driver parar a operação depois de ter processado o erro ou aviso, devolve SQL_ERROR.

Se o driver devolver algum aviso, como SQLSTATE 01004 (Dados truncados), devolve avisos que se aplicam a todo o conjunto de linhas ou a linhas desconhecidas antes de devolver a informação de erro aplicável a linhas específicas. Devolve avisos para linhas específicas juntamente com qualquer outra informação de erro sobre essas linhas.

Se RowNumber for igual a 0 e Operation for SQL_UPDATE, SQL_REFRESH ou SQL_DELETE, o número de linhas em que o SQLSetPos opera é apontado pelo atributo da instrução SQL_ATTR_ROWS_FETCHED_PTR.

Se RowNumber for igual a 0 e Operation for SQL_DELETE, SQL_REFRESH ou SQL_UPDATE, a linha atual após a operação é igual à linha atual antes da operação.

Ignorar uma discussão numa operação em massa

O array de operações de linhas pode ser usado para indicar que uma linha no conjunto de linhas atual deve ser ignorada durante uma operação em massa usando SQLSetPos. Para direcionar o driver a ignorar uma ou mais linhas durante uma operação em bloco, uma aplicação deve executar os seguintes passos:

  1. Chame SQLSetStmtAttr para definir o atributo da instrução SQL_ATTR_ROW_OPERATION_PTR para apontar para um array de SQLUSMALLINTs. Este campo também pode ser definido chamando SQLSetDescField para definir o campo de cabeçalho SQL_DESC_ARRAY_STATUS_PTR do ARD, o que requer que uma aplicação obtenha o handle do descriptor.

  2. Defina cada elemento do array de operações de linha para um de dois valores:

    • SQL_ROW_IGNORE, para indicar que a linha está excluída para a operação em massa.

    • SQL_ROW_PROCEED, para indicar que a linha está incluída na operação em bloco. (Este é o valor padrão.)

  3. Ligue para o SQLSetPos para realizar a operação em massa.

As seguintes regras aplicam-se ao array de operações de linhas:

  • SQL_ROW_IGNORE e SQL_ROW_PROCEED afetam apenas operações em massa usando SQLSetPos com uma Operação de SQL_DELETE ou SQL_UPDATE. Não afetam chamadas para SQLSetPos com uma Operação de SQL_REFRESH ou SQL_POSITION.

  • O ponteiro está definido como nulo por defeito.

  • Se o ponteiro for nulo, todas as linhas são atualizadas como se todos os elementos estivessem definidos para SQL_ROW_PROCEED.

  • Definir um elemento para SQL_ROW_PROCEED não garante que a operação ocorra nessa linha em particular. Por exemplo, se uma certa linha no conjunto de linhas tiver o estado SQL_ROW_ERROR, o driver pode não conseguir atualizar essa linha independentemente de a aplicação especificar SQL_ROW_PROCEED. Uma aplicação deve sempre verificar o array de estado das linhas para verificar se a operação foi bem-sucedida.

  • SQL_ROW_PROCEED é definido como 0 no ficheiro de cabeçalho. Uma aplicação pode inicializar o array de operações de linhas a 0 para processar todas as linhas.

  • Se o elemento número "n" no array de operações de linhas for definido para SQL_ROW_IGNORE e o SQLSetPos for chamado para realizar uma operação de atualização ou eliminação em massa, a enésima linha no conjunto de linhas permanece inalterada após a chamada ao SQLSetPos.

  • Uma aplicação deve definir automaticamente uma coluna de somente leitura para SQL_ROW_IGNORE.

Ignorar uma coluna numa operação em massa

Para evitar diagnósticos de processamento desnecessários gerados por tentativas de atualizações a uma ou mais colunas de apenas leitura, uma aplicação pode definir o valor no buffer de comprimento/indicador limitado para SQL_COLUMN_IGNORE. Para mais informações, consulte SQLBindCol.

Exemplo de código

No exemplo seguinte, uma aplicação permite ao utilizador navegar pela tabela ORDERS e atualizar o estado da encomenda. O cursor é controlado por conjuntos de chaves, com um tamanho de conjunto de linhas de 20, e utiliza controlo otimista de concorrência para comparar as versões das linhas. Depois de cada conjunto de linhas ser obtido, a aplicação imprime-o e permite ao utilizador selecionar e atualizar o estado de uma encomenda. A aplicação utiliza SQLSetPos para posicionar o cursor na linha selecionada e realiza uma atualização posicionada da linha. (O tratamento de erros é omitido para maior clareza.)

#define ROWS 20  
#define STATUS_LEN 6  
  
SQLCHAR        szStatus[ROWS][STATUS_LEN], szReply[3];  
SQLINTEGER     cbStatus[ROWS], cbOrderID;  
SQLUSMALLINT   rgfRowStatus[ROWS];  
SQLUINTEGER    sOrderID, crow = ROWS, irow;  
SQLHSTMT       hstmtS, hstmtU;  
  
SQLSetStmtAttr(hstmtS, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) rgfRowStatus, 0);  
SQLSetCursorName(hstmtS, "C1", SQL_NTS);  
SQLExecDirect(hstmtS, "SELECT ORDERID, STATUS FROM ORDERS ", SQL_NTS);  
  
SQLBindCol(hstmtS, 1, SQL_C_ULONG, &sOrderID, 0, &cbOrderID);  
SQLBindCol(hstmtS, 2, SQL_C_CHAR, szStatus, STATUS_LEN, &cbStatus);  
  
while ((retcode == SQLFetchScroll(hstmtS, SQL_FETCH_NEXT, 0)) != SQL_ERROR) {  
   if (retcode == SQL_NO_DATA_FOUND)  
      break;  
   for (irow = 0; irow < crow; irow++) {  
      if (rgfRowStatus[irow] != SQL_ROW_DELETED)  
         printf("%2d %5d %*s\n", irow+1, sOrderID, NAME_LEN-1, szStatus[irow]);  
   }  
   while (TRUE) {  
      printf("\nRow number to update?");  
      gets_s(szReply, 3);  
      irow = atoi(szReply);  
      if (irow > 0 && irow <= crow) {  
         printf("\nNew status?");  
         gets_s(szStatus[irow-1], (ROWS * STATUS_LEN));  
         SQLSetPos(hstmtS, irow, SQL_POSITION, SQL_LOCK_NO_CHANGE);  
         SQLPrepare(hstmtU,  
          "UPDATE ORDERS SET STATUS=? WHERE CURRENT OF C1", SQL_NTS);  
         SQLBindParameter(hstmtU, 1, SQL_PARAM_INPUT,  
            SQL_C_CHAR, SQL_CHAR,  
            STATUS_LEN, 0, szStatus[irow], 0, NULL);  
         SQLExecute(hstmtU);  
      } else if (irow == 0) {  
         break;  
      }  
   }  
}  

Para mais exemplos, consulte Instruções de Atualização e Eliminação Posicionadas e Atualização de Linhas no Conjunto de Linhas com SQLSetPos.

Para obter informações sobre Veja
Ligar um buffer a uma coluna num conjunto de resultados Função SQLBindCol
Realizar operações em massa que não estejam relacionadas com a posição do cursor de bloco Função SQLBulkOperations
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
Definir um atributo de instrução Função SQLSetStmtAttr