Função SQLSetPos

Conformidade
Versão introduzida: ODBC 1.0 Standards Compliance: 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

StatementHandle
[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 se aplicará a cada linha no conjunto de linhas.

Para obter informações adicionais, confira "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 por 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, confira "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, confira "Comentários".

Retornos

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 Identificador 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 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO será retornado se ocorrer um erro em uma ou mais linhas de uma operação de várias linhas e SQL_ERROR será retornada 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 para mais de uma linha, consulte a descrição do atributo SQL_ATTR_SIMULATE_CURSOR em SQLSetStmtAttr.) (A função retorna SQL_SUCCESS_WITH_INFO.)

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

(SQL_SUCCESS_WITH_INFO será retornado se ocorrer um erro em uma ou mais linhas de uma operação multilinha, e SQL_ERROR será 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 de aplicativo não foi SQL_C_CHAR ou SQL_C_BINARY e os dados retornados aos buffers de 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 time, timestamp e interval que contêm 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 no tipo de dados especificado por TargetType na chamada para SQLBindCol.
07009 Índice de descritor inválido O argumento Operação 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 Operação foi SQL_UPDATE e nenhuma coluna foi atualizável porque todas as colunas estavam desassociadas, somente leitura ou o valor no buffer de comprimento/indicador associado foi SQL_COLUMN_IGNORE.
22001 Dados de cadeia de caracteres, truncamento correto 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 nãoblank (para caracteres) ou não nulo (para caracteres binários) ou bytes.
22003 Valor numérico fora do intervalo O argumento Operação 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 vez de fracionária) do número fosse truncada.

O argumento Operação 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 datetime inválido O argumento Operação 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 ano, mês ou dia estivesse fora do intervalo.

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

O argumento Operação foi SQL_REFRESH e o desempenho da aritmética datetime nos dados recuperados do conjunto de resultados resultou em um campo datetime (ano, mês, dia, hora, minuto ou segundo campo) do resultado fora do intervalo permitido de valores para o campo ou inválido com base nas regras naturais do calendário gregoriano para datetimes.
22015 Estouro de campo de intervalo O argumento Operation foi SQL_UPDATE e a atribuição de um tipo C numérico ou intervalo exato 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 do intervalo.

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

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 do intervalo.
22018 Valor de caractere inválido para especificação de conversão O argumento Operação foi SQL_REFRESH; o tipo C era um 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 Operação foi SQL_UPDATE; o tipo SQL era um numérico exato ou aproximado, um datetime ou um tipo de dados de intervalo; o tipo C foi SQL_C_CHAR; e o valor na coluna não era um literal válido do tipo SQL associado.
23000 Violação da restrição de integridade O argumento Operação foi SQL_DELETE ou SQL_UPDATE e uma restrição de integridade foi violada.
24.000 Estado de cursor inválido StatementHandle estava em um estado executado, mas nenhum conjunto de resultados foi associado ao StatementHandle.

(DM) Um cursor foi aberto no StatementHandle, mas SQLFetch ou SQLFetchScroll não foram chamados.

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

O argumento Operação 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 na 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 pôde bloquear a linha conforme necessário para executar a operação solicitada na operação de argumento.

O driver não pôde 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 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 nenhum SQLSTATE específico e para o qual nenhum SQLSTATE específico da implementação foi definido. A mensagem de erro retornada por SQLGetDiagRec no buffer *MessageText descreve o erro e sua causa.
HY001 Erro de alocação de memória O driver não pôde alocar a memória necessária para dar suporte à execução ou à conclusão da função.
HY008 Operação cancelada O processamento assíncrono foi habilitado para 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ções (DM) Uma função em 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 StatementHandle e ainda estava em execução quando essa função foi chamada.

(DM) SQLExecute, SQLExecDirect, SQLBulkOperations ou SQLSetPos foram chamados para StatementHandle e retornados SQL_NEED_DATA. Essa função foi chamada antes de os dados serem enviados para todos os parâmetros ou colunas de dados em execução.

(DM) 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 Comprimento de buffer ou cadeia de caracteres inválido O argumento Operation foi SQL_UPDATE, um valor de dados era um ponteiro nulo e o valor de 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 foi SQL_UPDATE; um valor de dados não era um ponteiro nulo; o tipo de dados C foi SQL_C_BINARY ou SQL_C_CHAR; e o valor de 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ções SQL_NEED_LONG_DATA_LEN no 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 foi SQL_UPDATE ou SQL_DELETE e o atributo de instrução SQL_ATTR_CONCURRENCY foi SQL_ATTR_CONCUR_READ_ONLY.
HY107 Valor de 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 encaminhamento, portanto, o cursor não pôde ser posicionado dentro do conjunto de linhas. Confira a descrição do atributo SQL_ATTR_CURSOR_TYPE em SQLSetStmtAttr.

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

(DM) O argumento RowNumber era 0 e o argumento Operation foi 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 de transação desconhecido. Somente funções desconectar 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 dá suporte à operação solicitada no argumento Operation ou no argumento LockType .
HYT00 Tempo limite esgotado O período de tempo limite da consulta expirou antes da fonte de dados retornar 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 da fonte de dados responder à solicitação. O período de tempo limite da conexão é definido por meio de SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT.
IM001 O driver não dá suporte a essa função (DM) O driver associado ao 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 a instrução informando que SQLSetPos pode ser chamado no e o que ele precisa fazer para compatibilidade com aplicativos ODBC 2.x , consulte Bloquear cursores, 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 se aplicará a cada linha no conjunto de linhas. RowNumber deve ser um valor de 0 para o 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 de 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 exigem uma posição de cursor:

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

  • Chama para SQLGetData.

  • Chama 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 de cursor quando chama SQLSetPos. Em geral, 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 têm suporte de uma fonte de dados, um aplicativo chama SQLGetInfo com o tipo de informações 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

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

O conteúdo da matriz de status de linha 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 por RowNumber e atualiza os dados nos buffers de conjunto de linhas dessa linha. Para obter mais informações sobre como o driver retorna dados nos buffers de conjunto de linhas, consulte as descrições da associação em linha e coluna no 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 indicadores. Como os dados nos buffers são atualizados, mas não são buscados novamente, a associação no conjunto de linhas é corrigida. Isso é diferente da atualização executada por uma chamada para SQLFetchScroll com uma FetchOrientation de SQL_FETCH_RELATIVE e um RowNumber igual a 0, que refeta 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á um status de 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 registros excluídos do pacote 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 que a simultaneidade do cursor seja atualizada sempre que os buffers de conjunto de linhas forem atualizados do servidor. Isso ocorre para cada linha atualizada.

O conteúdo da matriz de status da linha apontada pelo atributo de instrução SQL_ATTR_ROW_OPERATION_PTR é ignorado para a Operação SQL_REFRESH.
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, confira "Status e Matrizes de Operação" posteriormente nesta referência de função.
SQL_DELETE O driver posiciona o cursor na linha especificada por RowNumber e exclui a linha de dados subjacente. Ele altera o elemento correspondente da matriz de status da linha para SQL_ROW_DELETED. Depois que a linha tiver sido 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 Operação definida 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, confira "Status e Matrizes de Operação" posteriormente nesta referência de função.

Argumento LockType

O argumento LockType fornece uma maneira de 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 SQLSetPos ter sido executado. 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 é fechado quando uma transação é 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 têm suporte de uma fonte de dados, um aplicativo chama SQLGetInfo com o tipo de informações 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 era antes de SQLSetPos ser chamado. Esse valor de LockType permite que 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 der suporte a 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 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 no 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 só terá êxito 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 obteve 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 o 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 o 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 da linha, consulte SQLFetch. Para obter informações sobre a matriz de operação de linha, confira "Ignorando uma linha em uma operação em massa", mais adiante nesta seção.

Usando SQLSetPos

Antes que um aplicativo chame 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 SQLSetPos, consulte Atualizando dados com 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 Operação definida 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 colunasde dados em execução. Normalmente, eles são 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 de 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 específico da fonte de dados longa e o driver retornar "Y" para o tipo de informações 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 deve ser um valor não negativo e é 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

    Parâmetros de dados em execução são parâmetros em uma instrução SQL para a qual 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

    Colunas de dados em execução são colunas em um conjunto de linhas para o qual os dados serão enviados com SQLPutData quando uma linha for atualizada com SQLSetPos. Eles sã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 tipo de dados específico de caractere, binário ou fonte de dados ou ao enviar dados binários C para uma coluna com um tipo de dados específico de fonte de dados, binário ou caractere.

  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 tiver sido executada com êxito, SQLParamData retornará SQL_SUCCESS ou SQL_SUCCESS_WITH_INFO; se a execução falhar, ela 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 que a linha apropriada 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 ele 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ções).

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; cancelar não afeta o estado do cursor ou a posição atual do cursor.

Quando select-list 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.

Executando 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ão SQLSTATE HY109 (posição de cursor inválida).

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

Se ocorrer um erro referente a uma única linha, o driver:

  • Define o elemento para a linha na matriz de status de linha apontada pelo atributo de instrução SQL_ATTR_ROW_STATUS_PTR como SQL_ROW_ERROR.

  • Posta 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 o aviso, se o driver concluir a operação para as linhas restantes no conjunto de linhas, ele retornará SQL_SUCCESS_WITH_INFO. Portanto, para cada linha que retornou um erro, a fila de erros contém zero ou mais SQLSTATEs adicionais. Se o driver parar a operação depois de processar o erro ou o 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, 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 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á a mesma da 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 exige 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 é 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 as operações em massa usando SQLSetPos com uma Operação de SQL_DELETE ou SQL_UPDATE. Elas 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 fossem 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 sido especificado SQL_ROW_PROCEED. Um aplicativo sempre deve 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ções de linha estiver definido como SQL_ROW_IGNORE e SQLSetPos for chamado para executar uma operação de atualização ou exclusão em massa, a nª 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 para 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 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
Associar um buffer a uma coluna em um conjunto de resultados Função SQLBindCol
Executando operações em massa que não estão relacionadas à posição do cursor de bloco Função SQLBulkOperations
Cancelando o processamento de instruções Função SQLCancel
Buscar um bloco de dados ou rolar 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
Configurando 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

Consulte Também

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