Partilhar via


Função SQLSetPos

Compatibilidade
Versão introduzida: ODBC 1.0 Conformidade com os padrões: ODBC

Resumo
SQLSetPos define a posição do cursor em um conjunto de linhas e permite que um aplicativo atualize dados no conjunto de linhas ou atualize ou exclua dados no conjunto de resultados.

Sintaxe

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

Argumentos

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

RowNumber
[Entrada] Posição da linha no conjunto de linhas no qual executar a operação especificada com o argumento Operation . Se RowNumber for 0, a operação será aplicada a toda linha no conjunto de linhas.

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

Operação
[Entrada] Operação a ser executada:

SQL_POSITION SQL_REFRESH SQL_UPDATE SQL_DELETE

Observação

O valor SQL_ADD para o argumento Operation foi preterido para ODBC 3.x. Os drivers ODBC 3.x precisarão dar suporte a SQL_ADD para compatibilidade com versões anteriores. Essa funcionalidade foi substituída por uma chamada para SQLBulkOperations com uma operação de SQL_ADD. Quando um aplicativo ODBC 3.x funciona com um driver ODBC 2.x , o Gerenciador de Driver mapeia uma chamada para SQLBulkOperations com uma Operação de SQL_ADD para SQLSetPos com uma Operação de SQL_ADD.

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

LockType
[Entrada] Especifica como bloquear a linha depois de executar a operação especificada no argumento Operation .

SQL_LOCK_NO_CHANGE SQL_LOCK_EXCLUSIVE SQL_LOCK_UNLOCK

Para obter 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 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 por SQLSetPos e explica cada um deles no contexto dessa função; a notação "(DM)" precede as descrições de SQLSTATEs retornadas pelo Gerenciador de Driver. O código de retorno associado a cada valor SQLSTATE é SQL_ERROR, a menos que indicado de outra forma.

Para todos os SQLSTATEs que podem retornar SQL_SUCCESS_WITH_INFO ou SQL_ERROR (exceto SQLSTATEs 01xxx), SQL_SUCCESS_WITH_INFO será retornado se ocorrer um erro em uma ou mais, mas não em todas, linhas de uma operação de várias linhas e SQL_ERROR será 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.)
01001 Conflito de operação do cursor O argumento Operation foi SQL_DELETE ou SQL_UPDATE e nenhuma linha ou mais de uma linha foi excluída ou atualizada. (Para obter mais informações sobre atualizações em mais de uma linha, consulte a descrição do SQL_ATTR_SIMULATE_CURSOR Atributo em SQLSetStmtAttr.) (A função retorna SQL_SUCCESS_WITH_INFO.)

O argumento Operation foi SQL_DELETE ou SQL_UPDATE e a operação falhou devido à simultaneidade otimista. (A função retorna SQL_SUCCESS_WITH_INFO.)
01004 Truncamento à direita de dados de cadeia de caracteres O argumento Operation foi SQL_REFRESH e os dados de cadeia de caracteres ou binários retornados para uma coluna ou colunas com um tipo de dados de SQL_C_CHAR ou SQL_C_BINARY resultaram no truncamento de caracteres não em branco ou dados binários não NULL.
01S01 Erro na linha O argumento RowNumber era 0 e ocorreu um erro em uma ou mais linhas durante a execução da operação especificada com o argumento Operation .

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

(Esse SQLSTATE é retornado somente quando SQLSetPos é chamado após SQLExtendedFetch, se o driver for um driver ODBC 2.x e a biblioteca de cursores não for usada.)
01S07 Truncamento fracionário O argumento Operation foi SQL_REFRESH, o tipo de dados do buffer do aplicativo não foi SQL_C_CHAR ou SQL_C_BINARY e os dados retornados aos buffers do aplicativo para uma ou mais colunas foram truncados. Para tipos de dados numéricos, a parte fracionária do número foi truncada. Para tipos de dados de tempo, carimbo de data/hora e intervalo contendo um componente de tempo, a parte 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 valor de dados de uma coluna no conjunto de resultados não pôde ser convertido para o tipo de dados especificado por TargetType na chamada para SQLBindCol.
07009 Índice de descritor inválido O argumento Operation foi SQL_REFRESH ou SQL_UPDATE e uma coluna foi associada a um número de coluna maior que o número de colunas no conjunto de resultados.
21S02 O grau da tabela derivada não corresponde à lista de colunas O argumento Operation foi SQL_UPDATE e nenhuma coluna foi atualizável porque todas as colunas não estavam associadas, somente leitura ou o valor no buffer de comprimento/indicador vinculado era SQL_COLUMN_IGNORE.
22001 Dados de cadeia de caracteres, truncamento à direita O argumento Operation foi SQL_UPDATE e a atribuição de um caractere ou valor binário a uma coluna resultou no truncamento 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 Operation foi SQL_UPDATE e a atribuição de um valor numérico a uma coluna no conjunto de resultados fez com que toda a parte (em oposição à fracionária) do número fosse truncada.

O argumento Operation foi SQL_REFRESH e retornar o valor numérico para uma ou mais colunas associadas teria causado uma perda de dígitos significativos.
22007 Formato de data e hora inválido O argumento Operation foi SQL_UPDATE e a atribuição de um valor de data ou carimbo de data/hora a uma coluna no conjunto de resultados fez com que o campo de ano, mês ou dia ficasse fora do intervalo.

O argumento Operation foi SQL_REFRESH e retornar o valor de data ou carimbo de data/hora para uma ou mais colunas acopladas faria com que o campo ano, mês ou dia ficasse fora do intervalo.
22008 Estouro de campo de data/hora O argumento Operation foi SQL_UPDATE e o desempenho da aritmética de data e hora nos dados enviados para uma coluna no conjunto de resultados resultou em um campo de data e hora (o campo de ano, mês, dia, hora, minuto ou segundo) do resultado estar fora do intervalo permitido de valores para o campo ou ser inválido com base nas regras naturais do calendário gregoriano para datas.

O argumento Operation foi SQL_REFRESH e o desempenho da aritmética de data e hora nos dados recuperados do conjunto de resultados resultou em um campo de data e hora (o campo de ano, mês, dia, hora, minuto ou segundo) do resultado estar fora do intervalo permitido de valores para o campo ou ser inválido com base nas regras naturais do calendário gregoriano para datas.
22015 Estouro de campo de intervalo O argumento Operation foi SQL_UPDATE e a atribuição de um tipo numérico exato ou de intervalo C a um tipo de dados SQL de intervalo causou uma perda de dígitos significativos.

O argumento Operation foi SQL_UPDATE; ao atribuir a um tipo SQL de intervalo, não houve representação do valor do tipo C no tipo SQL de intervalo.

O argumento Operation foi SQL_REFRESH e atribuir de um tipo SQL numérico ou de intervalo exato a um tipo C de intervalo causou uma perda de dígitos significativos no campo principal.

O argumento Operation foi SQL_ REFRESH; ao atribuir a um tipo C de intervalo, não houve representação do valor do tipo SQL no tipo C de intervalo.
22018 Valor de caractere inválido para especificação de conversão O argumento Operation era SQL_REFRESH; o tipo C era um tipo de dados numérico exato ou aproximado, um datetime ou um tipo de dados de intervalo; o tipo SQL da coluna era um tipo de dados de caractere; e o valor na coluna não era um literal válido do tipo C associado.

O argumento Operation era SQL_UPDATE; o tipo SQL era um tipo de dados numérico exato ou aproximado, datetime ou intervalo; o tipo C era SQL_C_CHAR; e o valor na coluna não era um literal válido do tipo SQL associado.
23000 Violação de restrição de integridade O argumento Operation foi SQL_DELETE ou SQL_UPDATE e uma restrição de integridade foi violada.
24000 Estado de cursor inválido O StatementHandle estava em um estado executado, mas nenhum conjunto de resultados foi associado ao StatementHandle.

(DM) Um cursor estava aberto no StatementHandle, mas SQLFetch ou SQLFetchScroll não havia sido chamado.

Um cursor estava aberto no StatementHandle e SQLFetch ou SQLFetchScroll havia sido chamado, mas o cursor foi posicionado antes do início do conjunto de resultados ou após o final do conjunto de resultados.

O argumento Operation foi SQL_DELETE, SQL_REFRESH ou SQL_UPDATE, e o cursor foi posicionado antes do início do conjunto de resultados ou após o final do conjunto de resultados.
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 bloquear a linha conforme necessário para executar a operação solicitada no argumento Operation.

O driver não conseguiu bloquear a linha conforme solicitado no argumento LockType.
44000 Violação COM OPÇÃO DE VERIFICAÇÃO O argumento Operation foi SQL_UPDATE e a atualização foi executada em uma tabela exibida ou em uma tabela derivada da tabela exibida que foi criada especificando WITH CHECK OPTION, de modo que uma ou mais linhas afetadas pela atualização não estarão mais presentes na tabela exibida.
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 e, 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 SQLSetPos foi chamada.

(DM) O StatementHandle especificado não estava em um estado executado. A função foi chamada sem primeiro 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, SQLBulkOperations ou SQLSetPos foi chamado para o StatementHandle e retornado SQL_NEED_DATA. Essa função foi chamada antes que os dados fossem enviados para todos os parâmetros ou colunas de dados em execução.

(DM) O driver era um driver ODBC 2.x e SQLSetPos foi chamado para um StatementHandle depois que SQLFetch foi chamado.
HY011 O atributo não pode ser definido agora (DM) O driver era um driver ODBC 2.x ; o atributo de instrução SQL_ATTR_ROW_STATUS_PTR foi definido; em seguida, SQLSetPos foi chamado antes de SQLFetch, SQLFetchScroll ou SQLExtendedFetch ser chamado.
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 Operation era SQL_UPDATE, um valor de dados 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 ou menor ou igual a SQL_LEN_DATA_AT_EXEC_OFFSET.

O argumento Operation era SQL_UPDATE; um valor de dados 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 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 foi SQL_DATA_AT_EXEC; o tipo SQL era SQL_LONGVARCHAR, SQL_LONGVARBINARY ou um tipo de dados específico da fonte de dados longa; e o tipo de informação SQL_NEED_LONG_DATA_LEN em SQLGetInfo era "Y".
HY092 Identificador de atributo inválido (DM) O valor especificado para o argumento Operation era inválido.

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

O argumento Operation era SQL_UPDATE ou SQL_DELETE, e o atributo SQL_ATTR_CONCURRENCY instrução era SQL_ATTR_CONCUR_READ_ONLY.
HY107 Valor da linha fora do intervalo O valor especificado para o argumento RowNumber era maior 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 somente para frente, portanto, o cursor não pôde ser posicionado dentro do conjunto de linhas. Consulte a descrição do atributo SQL_ATTR_CURSOR_TYPE em SQLSetStmtAttr.

O argumento Operation era SQL_UPDATE, SQL_DELETE ou SQL_REFRESH, e a linha identificada pelo argumento RowNumber havia sido excluída ou não havia sido buscada.

(DM) O argumento RowNumber era 0 e o argumento Operation era SQL_POSITION.

SQLSetPos foi chamado depois que SQLBulkOperations foi chamado e antes de SQLFetchScroll ou SQLFetch ser chamado.
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 a fonte de dados não dá suporte à operação solicitada no argumento Operation ou no argumento LockType.
HYT00 Timeout expired 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 limite é definido por meio de SQLSetStmtAttr com um 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.

Comentários

Cuidado

Para obter informações sobre os estados de instrução que SQLSetPos podem ser chamados e o que ele precisa fazer para compatibilidade com aplicativos ODBC 2.x , consulte Cursores de bloco, cursores roláveis e compatibilidade com versões anteriores.

Argumento RowNumber

O argumento RowNumber especifica o número da linha no conjunto de linhas no qual executar a operação especificada pelo argumento Operation . Se RowNumber for 0, a operação será aplicada a toda linha no conjunto de linhas. RowNumber deve ser um valor de 0 ao número de linhas no conjunto de linhas.

Observação

Na linguagem C, as matrizes são baseadas em 0 e o argumento RowNumber é baseado em 1. Por exemplo, para atualizar a quinta linha do conjunto de linhas, um aplicativo modifica os buffers do conjunto de linhas no índice de matriz 4, mas especifica um RowNumber de 5.

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

  • Instruções de atualização e exclusão posicionadas.

  • 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 para SQLSetPos com uma Operação de SQL_DELETE, o cursor será posicionado na segunda linha do conjunto de linhas e essa linha será excluída. A entrada na matriz de status da linha de implementação (apontada pelo atributo de instrução SQL_ATTR_ROW_STATUS_PTR) para a segunda linha é alterada para SQL_ROW_DELETED.

Um aplicativo pode especificar uma posição do cursor quando chama SQLSetPos. Geralmente, ele 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 exclusão posicionada ou chamar SQLGetData.

Argumento de operação

O argumento Operation dá suporte às operações a seguir. Para determinar quais opções são suportadas por uma fonte de dados, um aplicativo 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).

Operação

argument
Operação
SQL_POSITION O driver posiciona o cursor na linha especificada por RowNumber.

O conteúdo da matriz de status da linha apontada pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR é ignorado para a SQL_POSITION Operação.
SQL_REFRESH O driver posiciona o cursor na linha especificada por RowNumber e atualiza os dados nos buffers do conjunto de linhas para essa linha. Para obter mais informações sobre como o driver retorna dados nos buffers do conjunto de linhas, consulte as descrições da associação de linha e coluna em SQLBindCol.

SQLSetPos com uma Operação de SQL_REFRESH atualiza o status e o conteúdo das linhas dentro do conjunto de linhas buscado atual. Isso inclui atualizar os favoritos. Como os dados nos buffers são atualizados, mas não buscados novamente, a associação no conjunto de linhas é corrigida. Isso é diferente da atualização executada por uma chamada para SQLFetchScroll com um FetchOrientation de SQL_FETCH_RELATIVE e um RowNumber igual a 0, que busca novamente o conjunto de linhas do conjunto de resultados para que ele possa mostrar dados adicionados e remover dados excluídos se essas operações forem compatíveis com o driver e o cursor.

Uma atualização bem-sucedida com SQLSetPos não alterará o status de uma linha de SQL_ROW_DELETED. As linhas excluídas dentro do conjunto de linhas continuarão a ser marcadas como excluídas até a próxima busca. As linhas desaparecerão na próxima busca se o cursor der suporte ao empacotamento (no qual um SQLFetch ou SQLFetchScroll subsequente não retorna linhas excluídas).

As linhas adicionadas não aparecem quando uma atualização com SQLSetPos é executada. Esse comportamento é diferente de 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á registros adicionados ou empacotará registros excluídos se essas operações forem compatíveis com o cursor.

Uma atualização bem-sucedida com SQLSetPos alterará um status de linha de SQL_ROW_ADDED para SQL_ROW_SUCCESS (se a matriz de status da linha existir).

Uma atualização bem-sucedida com SQLSetPos alterará um status de linha de SQL_ROW_UPDATED para o novo status da linha (se a matriz de status da linha existir).

Se ocorrer um erro em uma operação SQLSetPos em uma linha, o status da linha será definido como SQL_ROW_ERROR (se a matriz de status da linha existir).

Para um cursor aberto com um atributo de instrução SQL_ATTR_CONCURRENCY de SQL_CONCUR_ROWVER ou SQL_CONCUR_VALUES, uma atualização com SQLSetPos pode atualizar os valores de simultaneidade otimista usados pela fonte de dados para detectar que a linha foi alterada. Se isso ocorrer, as versões de linha ou os valores usados para garantir a simultaneidade do cursor serão atualizados sempre que os buffers do conjunto de linhas forem atualizados do servidor. Isso ocorre para cada linha que é atualizada.

O conteúdo da matriz de status da linha apontada pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR é ignorado para a SQL_REFRESH Operation.
SQL_UPDATE O driver posiciona o cursor na linha especificada por RowNumber e atualiza a linha subjacente de dados com os valores nos buffers do conjunto de linhas (o argumento TargetValuePtr em SQLBindCol). Ele recupera os comprimentos dos dados dos buffers de comprimento/indicador (o argumento StrLen_or_IndPtr em SQLBindCol). Se o comprimento de qualquer coluna for SQL_COLUMN_IGNORE, a coluna não será atualizada. Depois de atualizar a linha, o driver altera o elemento correspondente da matriz de status da linha para SQL_ROW_UPDATED ou SQL_ROW_SUCCESS_WITH_INFO (se a matriz de status da linha existir).

É definido pelo driver qual é o comportamento se SQLSetPos com um argumento Operation de SQL_UPDATE for chamado em um cursor que contém colunas duplicadas. O driver pode retornar um SQLSTATE definido pelo driver, pode atualizar a primeira coluna que aparece no conjunto de resultados ou executar outro comportamento definido pelo driver.

A matriz de operação de linha apontada pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR pode ser usada para indicar que uma linha no conjunto de linhas atual deve ser ignorada durante uma atualização em massa. Para obter mais informações, consulte "Matrizes de status e operação" mais adiante nesta referência de função.
SQL_DELETE O driver posiciona o cursor na linha especificada por RowNumber e exclui a linha subjacente de dados. Ele altera o elemento correspondente da matriz de status da linha para SQL_ROW_DELETED. Depois que a linha for excluída, o seguinte não será válido para a linha: instruções de atualização e exclusão posicionadas, chamadas para SQLGetData e chamadas para SQLSetPos com Operation definido como qualquer coisa, exceto SQL_POSITION. Para drivers que dão suporte ao empacotamento, a linha é excluída 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, as linhas excluídas são visíveis para cursores estáticos e controlados por conjunto de chaves, mas invisíveis para cursores dinâmicos.

A matriz de operação de linha apontada pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR pode ser usada para indicar que uma linha no conjunto de linhas atual deve ser ignorada durante uma exclusão em massa. Para obter mais informações, consulte "Matrizes de status e operação" mais adiante nesta referência de função.

Argumento LockType

O argumento LockType fornece uma maneira para os aplicativos controlarem a simultaneidade. Na maioria dos casos, as fontes de dados que dão suporte a níveis de simultaneidade e transações darão suporte apenas ao valor SQL_LOCK_NO_CHANGE do argumento LockType . O argumento LockType geralmente é usado apenas para suporte baseado em arquivo.

O argumento LockType especifica o estado de bloqueio da linha após a execução de SQLSetPos . Se o driver não conseguir bloquear a linha para executar a operação solicitada ou para atender ao argumento LockType , ele retornará SQL_ERROR e SQLSTATE 42000 (erro de sintaxe ou violação de acesso).

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

Uma linha bloqueada por meio de SQLSetPos permanece bloqueada até que o aplicativo chame SQLSetPos para a linha com LockType definido como SQL_LOCK_UNLOCK ou até que o aplicativo chame SQLFreeHandle para a instrução ou SQLFreeStmt com a opção SQL_CLOSE. Para um driver que dá suporte a transações, uma linha bloqueada por meio de SQLSetPos é desbloqueada quando o aplicativo chama SQLEndTran para confirmar ou reverter uma transação na conexão (se um cursor for fechado quando uma transação for confirmada ou revertida, conforme indicado pelos tipos de informações SQL_CURSOR_COMMIT_BEHAVIOR e SQL_CURSOR_ROLLBACK_BEHAVIOR retornados por SQLGetInfo).

O argumento LockType dá suporte aos seguintes tipos de bloqueios. Para determinar quais bloqueios são suportados por uma fonte de dados, um aplicativo 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 LockType Tipo de bloqueio
SQL_LOCK_NO_CHANGE O driver ou a fonte de dados garante que a linha esteja no mesmo estado bloqueado ou desbloqueado que estava antes de SQLSetPos ser chamado. Esse valor de LockType permite que as fontes de dados que não dão suporte ao bloqueio explícito em nível de linha usem qualquer bloqueio exigido pelos níveis atuais de simultaneidade e isolamento de transação.
SQL_LOCK_EXCLUSIVE O driver ou a fonte de dados bloqueia a linha exclusivamente. Uma instrução em uma conexão diferente ou em um aplicativo diferente não pode ser usada para adquirir bloqueios na linha.
SQL_LOCK_UNLOCK O driver ou a fonte de dados desbloqueia a linha.

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

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

Para as operações de atualização e exclusão em SQLSetPos, o aplicativo usa o argumento LockType da seguinte maneira:

  • Para garantir que uma linha não seja alterada depois de recuperada, um aplicativo chama SQLSetPos com Operation definido como SQL_REFRESH e LockType definido como SQL_LOCK_EXCLUSIVE.

  • Se o aplicativo definir LockType como SQL_LOCK_NO_CHANGE, o driver garantirá que uma operação de atualização ou exclusão será bem-sucedida somente se o aplicativo especificado SQL_CONCUR_LOCK para o atributo de instrução SQL_ATTR_CONCURRENCY.

  • Se o aplicativo especificar SQL_CONCUR_ROWVER ou SQL_CONCUR_VALUES para o atributo de instrução SQL_ATTR_CONCURRENCY, o driver comparará versões ou valores de linha e rejeitará a operação se a linha tiver sido alterada desde que o aplicativo buscou a linha.

  • Se o aplicativo especificar SQL_CONCUR_READ_ONLY para o atributo de instrução SQL_ATTR_CONCURRENCY, o driver rejeitará qualquer operação de atualização ou exclusão.

Para obter mais informações sobre o atributo de instrução SQL_ATTR_CONCURRENCY, consulte SQLSetStmtAttr.

Matrizes de status e operação

As seguintes matrizes de status e operação são usadas ao chamar SQLSetPos:

  • A matriz de status da linha (conforme apontado pelo campo SQL_DESC_ARRAY_STATUS_PTR no IRD e no atributo de instrução SQL_ATTR_ROW_STATUS_ARRAY) contém valores de status para cada linha de dados no conjunto de linhas. O driver define os valores de status nessa matriz após uma chamada para SQLFetch, SQLFetchScroll, SQLBulkOperations ou SQLSetPos. Essa matriz é apontada pelo atributo de instrução SQL_ATTR_ROW_STATUS_PTR.

  • A matriz de operação de linha (conforme apontado pelo campo SQL_DESC_ARRAY_STATUS_PTR no ARD e no atributo de instrução SQL_ATTR_ROW_OPERATION_ARRAY) contém um valor para cada linha no conjunto de linhas que indica se uma chamada para SQLSetPos para uma operação em massa é ignorada ou executada. Cada elemento na matriz é definido como SQL_ROW_PROCEED (o padrão) ou SQL_ROW_IGNORE. Essa matriz é apontada pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR.

O número de elementos nas matrizes de status 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 obter informações sobre a matriz de status de linha, consulte SQLFetch. Para obter informações sobre a matriz de operação de linha, consulte "Ignorando uma linha em uma operação em massa", mais adiante nesta seção.

Usando SQLSetPos

Antes de um aplicativo chamar SQLSetPos, ele deve executar a seguinte sequência de etapas:

  1. Se o aplicativo chamar SQLSetPos com Operation definido como SQL_UPDATE , chame SQLBindCol (ou SQLSetDescRec) para cada coluna para especificar seu tipo de dados e associar buffers para os dados e o comprimento da coluna.

  2. Se o aplicativo chamar SQLSetPos com Operation definido como SQL_DELETE ou SQL_UPDATE, chame SQLColAttribute para garantir que as colunas a serem excluídas ou atualizadas sejam 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 obter mais informações sobre como usar o SQLSetPos, consulte Atualizando dados com o SQLSetPos.

Excluindo dados usando SQLSetPos

Para excluir dados com SQLSetPos, um aplicativo chama SQLSetPos com RowNumber definido como o número da linha a ser excluída e Operation definido como SQL_DELETE.

Depois que os dados forem excluídos, o driver alterará o valor na matriz de status da linha de implementação da linha apropriada para SQL_ROW_DELETED (ou SQL_ROW_ERROR).

Atualizando dados usando SQLSetPos

Um aplicativo pode passar o valor de uma coluna no buffer de dados associado ou com uma ou mais chamadas para SQLPutData. As colunas cujos dados são passados com SQLPutData são conhecidas como colunas de dados em execução. Eles são comumente usados para enviar dados para colunas SQL_LONGVARBINARY e SQL_LONGVARCHAR e podem ser misturados com outras colunas.

Para atualizar dados com SQLSetPos, um aplicativo:

  1. Coloca valores nos buffers de dados e comprimento/indicador associados a SQLBindCol:

    • Para colunas normais, o aplicativo coloca o novo valor da coluna no buffer *TargetValuePtr e o comprimento desse valor no buffer *StrLen_or_IndPtr . Se a linha não deve ser atualizada, o aplicativo coloca SQL_ROW_IGNORE no elemento dessa linha da matriz de operação de linha.

    • Para colunas de dados em execução, o aplicativo coloca um valor definido pelo aplicativo, como o número da coluna, no buffer *TargetValuePtr . O valor pode ser usado posteriormente para identificar a coluna.

      O aplicativo coloca o resultado da macro SQL_LEN_DATA_AT_EXEC(length) no buffer *StrLen_or_IndPtr . Se o tipo de dados SQL da coluna for SQL_LONGVARBINARY, SQL_LONGVARCHAR ou um tipo de dados longo específico da fonte de dados e o driver retornar "Y" para o tipo de informação SQL_NEED_LONG_DATA_LEN em SQLGetInfo, length será o número de bytes de dados a serem enviados para o parâmetro; caso contrário, ele deverá ser um valor não negativo e será ignorado.

  2. Chama SQLSetPos com o argumento Operation definido como SQL_UPDATE para atualizar a linha de dados.

    • Se não houver colunas de dados em execução, o processo será concluído.

    • Se houver colunas de dados em execução, a função retornará SQL_NEED_DATA e prosseguirá para a etapa 3.

  3. Chama SQLParamData para recuperar o endereço do buffer *TargetValuePtr para a primeira coluna de dados em execução a ser processada. SQLParamData retorna SQL_NEED_DATA. O aplicativo recupera o valor definido pelo aplicativo do buffer *TargetValuePtr .

    Observação

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

    Observação

    Os parâmetros de dados em execução são parâmetros em uma instrução SQL para os quais os dados serão enviados com SQLPutData quando a instrução for executada com SQLExecDirect ou SQLExecute. Eles são associados a SQLBindParameter ou definindo descritores com SQLSetDescRec. O valor retornado por SQLParamData é um valor de 32 bits passado para SQLBindParameter no argumento ParameterValuePtr .

    Observação

    As colunas de dados em 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 com SQLSetPos. Eles estão associados a SQLBindCol. O valor retornado por SQLParamData é o endereço da linha no buffer *TargetValuePtr que está sendo processado.

  4. Chama SQLPutData uma ou mais vezes para enviar dados para a coluna. Mais de uma chamada será necessária se todos os valores de dados não puderem ser retornados no buffer *TargetValuePtr especificado em SQLPutData; várias chamadas para SQLPutData para a mesma coluna são permitidas somente ao enviar dados de caractere C para uma coluna com um caractere, binário ou tipo de dados específico da fonte de dados ou ao enviar dados binários C para uma coluna com um caractere, binário ou tipo de dados específico da fonte de dados.

  5. Chama SQLParamData novamente para sinalizar que todos os dados foram enviados para a coluna.

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

    • Se não houver mais colunas de dados em execução, o processo será concluído. Se a instrução foi executada com êxito, SQLParamData retornará SQL_SUCCESS ou SQL_SUCCESS_WITH_INFO; se a execução falhar, ele retornará SQL_ERROR. Neste ponto, SQLParamData pode retornar qualquer SQLSTATE que possa ser retornado por SQLSetPos.

Se os dados tiverem sido atualizados, o driver alterará o valor na matriz de status da linha de implementação para a linha apropriada para SQL_ROW_UPDATED.

Se a operação for cancelada ou ocorrer um erro em SQLParamData ou SQLPutData, depois que SQLSetPos retornar SQL_NEED_DATA e antes que os dados sejam enviados para todas as colunas de dados em execução, o aplicativo poderá 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 retornará SQL_ERROR e SQLSTATE HY010 (erro de sequência de função).

Se o aplicativo chamar SQLCancel enquanto o driver ainda precisar de dados para colunas de dados em execução, o driver cancelará a operação. Em seguida, o aplicativo pode chamar SQLSetPos novamente; o cancelamento não afeta o estado do cursor ou a posição atual do cursor.

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

Execução de operações em massa

Se o argumento RowNumber for 0, o driver executará a operação especificada no argumento Operation para cada linha no conjunto de linhas que tem um valor de SQL_ROW_PROCEED em seu campo na matriz de operação de linha apontada por SQL_ATTR_ROW_OPERATION_PTR atributo de instrução. Esse é um valor válido do argumento RowNumber para um argumento Operation de SQL_DELETE, SQL_REFRESH ou SQL_UPDATE, mas não SQL_POSITION. SQLSetPos com uma operação de SQL_POSITION e um RowNumber igual a 0 retornará SQLSTATE HY109 (posição inválida do cursor).

Se ocorrer um erro que pertença a todo o conjunto de linhas, como SQLSTATE HYT00 (Tempo limite expirado), o driver retornará SQL_ERROR e o SQLSTATE apropriado. O conteúdo dos buffers do conjunto de linhas é indefinido e a posição do cursor permanece inalterada.

Se ocorrer um erro que pertença a uma única linha, o driver:

  • Define o elemento da linha na matriz de status da linha apontada pelo atributo de 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 no conjunto de linhas, ele retornará SQL_SUCCESS_WITH_INFO. Assim, para cada linha que retornou um erro, a fila de erros contém zero ou mais SQLSTATEs adicionais. Se o driver interromper a operação depois de processar o erro ou aviso, ele retornará SQL_ERROR.

Se o driver retornar avisos, como SQLSTATE 01004 (Dados truncados), ele retornará avisos que se aplicam a todo o conjunto de linhas ou a linhas desconhecidas no conjunto de linhas antes de retornar as informações de erro que se aplicam a linhas específicas. Ele retorna avisos para linhas específicas junto 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 SQLSetPos opera será apontado pelo atributo de 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 será igual à linha atual antes da operação.

Ignorando uma linha em uma operação em massa

A matriz de operação de linha pode ser usada 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 massa, um aplicativo deve executar as seguintes etapas:

  1. Chame SQLSetStmtAttr para definir o atributo de instrução SQL_ATTR_ROW_OPERATION_PTR para apontar para uma matriz de SQLUSMALLINTs. Esse 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 um aplicativo obtenha o identificador do descritor.

  2. Defina cada elemento da matriz de operação de linha como um dos dois valores:

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

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

  3. Chame SQLSetPos para executar a operação em massa.

As seguintes regras se aplicam à matriz de operação de linha:

  • 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. Eles não afetam chamadas para SQLSetPos com uma operação de SQL_REFRESH ou SQL_POSITION.

  • O ponteiro é definido como nulo por padrão.

  • Se o ponteiro for nulo, todas as linhas serão atualizadas como se todos os elementos tivessem sido definidos como SQL_ROW_PROCEED.

  • Definir um elemento como SQL_ROW_PROCEED não garante que a operação ocorrerá nessa linha específica. Por exemplo, se uma determinada linha no conjunto de linhas tiver o status SQL_ROW_ERROR, o driver poderá não ser capaz de atualizar essa linha, independentemente de o aplicativo ter especificado SQL_ROW_PROCEED. Um aplicativo deve sempre verificar a matriz de status da linha para ver se a operação foi bem-sucedida.

  • SQL_ROW_PROCEED é definido como 0 no arquivo de cabeçalho. Um aplicativo pode inicializar a matriz de operação de linha como 0 para processar todas as linhas.

  • Se o número do elemento "n" na matriz de operação de linha for definido como SQL_ROW_IGNORE e SQLSetPos for chamado para executar uma operação de atualização ou exclusão em massa, a enésima linha no conjunto de linhas permanecerá inalterada após a chamada para SQLSetPos.

  • Um aplicativo deve definir automaticamente uma coluna somente leitura como SQL_ROW_IGNORE.

Ignorando uma coluna em uma operação em massa

Para evitar diagnósticos de processamento desnecessários gerados por tentativas de atualizações em uma ou mais colunas somente leitura, um aplicativo pode definir o valor no buffer de comprimento/indicador associado como SQL_COLUMN_IGNORE. Para obter mais informações, consulte SQLBindCol.

Exemplo de código

No exemplo a seguir, um aplicativo permite que um usuário navegue na tabela ORDERS e atualize o status do pedido. O cursor é controlado por conjunto de chaves com um tamanho de conjunto de linhas de 20 e usa o controle de simultaneidade otimista comparando versões de linha. Depois que cada conjunto de linhas é buscado, o aplicativo o imprime e permite que o usuário selecione e atualize o status de um pedido. O aplicativo usa SQLSetPos para posicionar o cursor na linha selecionada e executa 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 obter mais exemplos, consulte Instruções de atualização e exclusão posicionadas e Atualizando linhas no conjunto de linhas com SQLSetPos.

Para obter informações sobre Consulte
Associando um buffer a uma coluna em um conjunto de resultados Função SQLBindCol
Executando operações em massa que não se relacionam com a posição do cursor de bloco Função SQLBulkOperations
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 vários campos de um descritor Função SQLGetDescRec
Definindo um único campo de um descritor Função SQLSetDescField
Definindo vários campos de um descritor Função SQLSetDescRec
Configurando um atributo de instrução Função SQLSetStmtAttr

Confira também

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