Noções básicas sobre tipos de cursor

Baixar driver JDBC

As operações numa base de dados relacional atuam sobre um conjunto completo de linhas. O conjunto de linhas devolvidas por uma instrução SELECT consiste em todas as linhas que satisfazem as condições da cláusula WHERE da sentença. Este conjunto completo de linhas devolvidas pela instrução é conhecido como conjunto de resultados. As aplicações nem sempre conseguem funcionar eficazmente com todo o conjunto de resultados como uma unidade. Estas aplicações precisam de uma forma de trabalhar com uma linha ou um pequeno bloco de linhas de cada vez. Os cursores são uma extensão dos conjuntos de resultados que fornecem esse mecanismo.

Os cursores estendem o processamento do conjunto de resultados fazendo os seguintes itens:

  • Permitindo posicionamento em linhas específicas do conjunto de resultados.
  • Recuperar uma linha ou bloco de linhas da posição atual no conjunto de resultados.
  • Apoiar modificações de dados na linha na posição atual no conjunto de resultados.
  • Suportando diferentes níveis de visibilidade às alterações feitas aos dados da base de dados por outros utilizadores que são apresentados no conjunto de resultados.

Observação

Para uma descrição completa dos tipos de cursores do SQL Server, veja Tipo de Cursores.

A especificação JDBC oferece suporte para cursores apenas avançados e roláveis que são sensíveis ou insensíveis a alterações feitas por outros trabalhos, podendo ser apenas leitura ou atualizáveis. Esta funcionalidade é fornecida pela classe SQLServerResultSet do Microsoft JDBC Driver para SQL ServerSQLServerResultSet.

Observações

O driver JDBC suporta o seguinte conjunto de resultados e tipos de cursor juntamente com as opções de comportamento especificadas.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) N/A Somente para avançar, somente leitura direto full

A aplicação tem de fazer uma única passagem (para a frente) pelo conjunto de resultados. Este passo é o comportamento padrão e funciona da mesma forma que um cursor TYPE_SS_DIRECT_FORWARD_ONLY. O driver lê todo o conjunto de resultados do servidor para uma memória durante o tempo de execução da instrução.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) N/A Somente para avançar, somente leitura direto adaptativo

A aplicação tem de fazer uma única passagem (para a frente) pelo conjunto de resultados. Comporta-se da mesma forma que um cursor TYPE_SS_DIRECT_FORWARD_ONLY. O driver lê linhas do servidor à medida que a aplicação as solicita e minimiza o uso de memória do lado do cliente.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) Avance Rápido Somente para avançar, somente leitura cursor N/A

A aplicação tem de fazer uma única passagem (para frente) através do conjunto de resultados usando um cursor de servidor. Comporta-se da mesma forma que um cursor do tipo TYPE_SS_SERVER_CURSOR_FORWARD_ONLY.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_FORWARD_ONLY (CONCUR_UPDATABLE) Dinâmica (Apenas para a frente) Apenas para a frente, atualizável N/A N/A

A aplicação tem de fazer uma única passagem (para a frente) pelo conjunto de resultados para atualizar uma ou mais linhas.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Por defeito, o tamanho do fetch é fixo quando a aplicação chama o método setFetchSize do objeto SQLServerResultSet .

Observação

O driver JDBC fornece uma funcionalidade de buffering adaptativo que permite recuperar os resultados da execução de instruções do SQL Server conforme a aplicação precisa, em vez de tudo de uma vez. Por exemplo, se a aplicação tiver de recuperar um grande volume de dados demasiado extenso para caber inteiramente na memória da aplicação, o buffering adaptativo permite à aplicação cliente recuperar tal valor em forma de fluxo. O comportamento padrão do driver é "adaptativo". No entanto, para obter o buffering adaptativo para os conjuntos de resultados atualizáveis apenas para frente, a aplicação tem de chamar explicitamente o método setResponseBuffering do objeto SQLServerStatement fornecendo um valor String "adaptativo". Para um exemplo de código, veja Atualização de grande amostra de dados.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SCROLL_INSENSITIVE Estático Scrollável, não atualizável.

As atualizações, inserções e eliminações externas de linhas não são visíveis.
N/A N/A

A aplicação requer um snapshot da base de dados. O conjunto de resultados não é atualizável. Só CONCUR_READ_ONLY é suportado. Todos os outros tipos de concorrência provocarão uma exceção quando utilizados com este tipo de cursor.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SCROLL_SENSITIVE (CONCUR_READ_ONLY) Conjunto de teclas Scrollável, só leitura. Atualizações externas de linhas são visíveis, e as remoções aparecem como dados ausentes.

As inserções externas das filas não são visíveis.
N/A N/A

A aplicação só precisa ver os dados alterados nas linhas existentes.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SCROLL_SENSITIVE (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) Conjunto de teclas Deslizável, atualizável.

Atualizações de linhas externas e internas são visíveis, e as eliminações aparecem como dados em falta; Os inserts não são visíveis.
N/A N/A

A aplicação pode alterar dados nas linhas existentes usando o objeto ResultSet. A aplicação deve também ser capaz de ver as alterações às linhas feitas por outros fora do objeto ResultSet.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SS_DIRECT_FORWARD_ONLY N/A Somente para avançar, somente leitura N/A Total ou adaptativo

Valor inteiro = 2003. Fornece um cursor do lado do cliente apenas de leitura que está totalmente armazenado em buffer. Não é criado nenhum cursor de servidor.

Apenas o modo de concorrência CONCUR_READ_ONLY é suportado. Todos os outros tipos de concorrência causam exceção quando usados com este tipo de cursor.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SS_SERVER_CURSOR_FORWARD_ONLY Avance Rápido Apenas avanço N/A N/A

Valor inteiro = 2004. Rápido e acede a todos os dados usando um cursor de servidor. É atualizável quando usado com o tipo de concorrência CONCUR_UPDATABLE.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Para obter buffering adaptativo neste caso, a aplicação tem de chamar explicitamente o método setResponseBuffering do objeto SQLServerStatement, fornecendo um valor String "adaptive". Para um exemplo de código, veja Atualização de grande amostra de dados.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SS_SCROLL_STATIC Estático As atualizações de outros utilizadores não são refletidas. N/A N/A

Valor inteiro = 1004. A aplicação requer um instantâneo da base de dados. Esta opção é o sinónimo específico do SQL Server para o TYPE_SCROLL_INSENSITIVE JDBC e tem o mesmo comportamento de configuração de concorrência.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
Tipo_SS_SCROLL_KEYSET (CONCUR_READ_ONLY) Conjunto de teclas Scrollável, só leitura. Atualizações externas de linhas são visíveis, e as remoções aparecem como dados ausentes.

As inserções externas das filas não são visíveis.
N/A N/A

Valor inteiro = 1005. O aplicativo deve visualizar os dados modificados apenas para as linhas existentes. Esta opção é o sinónimo específico do SQL Server para o TYPE_SCROLL_SENSITIVE JDBC e tem o mesmo comportamento de configuração de concorrência.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SS_SCROLL_KEYSET (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) Conjunto de teclas Deslizável, atualizável.

Atualizações de linhas externas e internas são visíveis, e as eliminações aparecem como dados em falta; Os inserts não são visíveis.
N/A N/A

Valor inteiro = 1005. A aplicação tem de alterar dados ou visualizar dados alterados para linhas existentes. Esta opção é o sinónimo específico do SQL Server para o TYPE_SCROLL_SENSITIVE JDBC e tem o mesmo comportamento de configuração de concorrência.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SS_SCROLL_DYNAMIC (CONCUR_READ_ONLY) Dynamic Scrollável, só leitura.

Atualizações e inserções externas de linhas ficam visíveis, e as eliminações aparecem como dados ausentes temporariamente no buffer de busca atual.
N/A N/A

Valor inteiro = 1006. A aplicação deve ver os dados alterados das linhas existentes e ver as linhas inseridas e eliminadas durante a vida útil do cursor.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Tipo de Conjunto de Resultados (Cursor) Tipo de Cursor SQL Server Caraterísticas selecionar Método Bufferização de resposta
TYPE_SS_SCROLL_DYNAMIC (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) Dynamic Deslizável, atualizável.

Atualizações e inserções externas e internas de linhas são visíveis, e as eliminações aparecem como dados temporariamente ausentes no buffer de busca atual.
N/A N/A

Valor inteiro = 1006. A aplicação pode alterar dados para linhas existentes, ou inserir ou eliminar linhas usando o objeto ResultSet. A aplicação deve também ser capaz de ver alterações, inserções e eliminações feitas por outros fora do objeto ResultSet.

As linhas são recuperadas do servidor em blocos especificados pelo tamanho do fetch.

Posicionamento do cursor

Os cursores TYPE_FORWARD_ONLY, TYPE_SS_DIRECT_FORWARD_ONLY e TYPE_SS_SERVER_CURSOR_FORWARD_ONLY suportam apenas o próximo método de posicionamento.

O cursor TYPE_SS_SCROLL_DYNAMIC não suporta os métodos absoluto e getRow . O método absoluto pode ser aproximado por uma combinação de chamadas aos primeiros métodos e métodos relativos para cursores dinâmicos.

O método getRow é suportado apenas por cursores TYPE_FORWARD_ONLY, TYPE_SS_DIRECT_FORWARD_ONLY, TYPE_SS_SERVER_CURSOR_FORWARD_ONLY, TYPE_SS_SCROLL_KEYSET e TYPE_SS_SCROLL_STATIC. O método getRow, com todos os tipos de cursor apenas para a frente, devolve o número de linhas lidas até agora através do cursor.

Observação

Quando uma aplicação faz uma chamada de posicionamento de cursor não suportada, ou uma chamada não suportada ao método getRow, é lançada uma exceção com a mensagem, "A operação solicitada não é suportada com este tipo de cursor."

Apenas os cursores TYPE_SS_SCROLL_KEYSET e os equivalentes TYPE_SCROLL_SENSITIVE expõem linhas apagadas. Se o cursor estiver posicionado numa linha eliminada, os valores das colunas não estão disponíveis, e o método rowDeleted devolve "true". Chamadas aos métodos get<Type> lançam uma exceção com a mensagem: "Não é possível obter o valor de uma linha eliminada". As linhas eliminadas não podem ser atualizadas. Se tentar chamar um método update<Type> numa linha eliminada, é lançada uma exceção com a mensagem "Uma linha eliminada não pode ser atualizada". O cursor TYPE_SS_SCROLL_DYNAMIC tem o mesmo comportamento até ser movido para fora do buffer de busca atual.

Cursores avançados e dinâmicos expõem linhas eliminadas de forma semelhante, mas apenas enquanto os cursores permanecem acessíveis no buffer de busca. No caso dos cursores avançados, este comportamento é bastante simples. Para cursores dinâmicos, é mais complexo quando o tamanho do fetch é maior que 1. Uma aplicação pode mover o cursor para a frente e para trás dentro da janela definida pelo fetch buffer, mas a linha eliminada desaparecerá quando o fetch buffer original, no qual foi atualizada, for deixado. Se uma aplicação não quiser ver linhas transitórias eliminadas ao utilizar cursores dinâmicos, deve ser utilizado um fetch relativo (0).

Se os valores-chave de uma linha de cursor TYPE_SS_SCROLL_KEYSET ou TYPE_SCROLL_SENSITIVE forem atualizados com o cursor, a linha mantém a sua posição original no conjunto de resultados, independentemente de a linha atualizada cumprir ou não os critérios de seleção do cursor. Se a linha foi atualizada fora do cursor, uma linha eliminada aparecerá na posição original da linha, mas a linha aparecerá no cursor apenas se outra linha com os novos valores-chave estivesse presente no cursor, tendo sido entretanto eliminada.

Para cursores dinâmicos, as linhas atualizadas mantêm a sua posição dentro do buffer de busca até que a janela definida pelo buffer de busca seja deixada. As linhas atualizadas podem mais tarde reaparecer em diferentes posições dentro do conjunto de resultados, ou podem desaparecer completamente. Aplicações que têm de evitar inconsistências transitórias no conjunto de resultados devem usar um fetch size de 1 (o padrão é 8 linhas com a concorrência CONCUR_SS_SCROLL_LOCKS e 128 linhas com outras opções de concorrência).

Conversão de cursor

O SQL Server pode, por vezes, optar por implementar um tipo de cursor diferente do solicitado, o que é referido como conversão implícita de cursor (ou degradação do cursor).

Com o SQL Server 2000 (8.x), quando atualizas os dados através do ResultSet.TYPE_SCROLL_SENSITIVE e do conjunto de resultados ResultSet.CONCUR_UPDATABLE, é lançada uma exceção com a mensagem "O cursor é SÓ LEITURA". Esta exceção ocorre porque o SQL Server 2000 (8.x) fez uma conversão implícita de cursor para esse conjunto de resultados e não devolveu o cursor atualizável que foi solicitado.

Para contornar este problema, pode optar por uma das seguintes soluções:

Atualização do cursor

Atualizações no local são suportadas para cursores onde o tipo de cursor e a concorrência suportam atualizações. Se o cursor não estiver posicionado numa linha atualizável no conjunto de resultados (nenhuma chamada do método get<Type> foi bem-sucedida), uma chamada a um método update<Type> lançará uma exceção com a mensagem, "O conjunto de resultados não tem linha corrente." A especificação JDBC afirma que surge uma exceção quando um método de atualização é chamado para uma coluna de um cursor que é CONCUR_READ_ONLY. Em situações em que a linha não é atualizável, como devido a um conflito otimista de concorrência, como uma atualização ou eliminação concorrente, a exceção pode não surgir até que insertRow, updateRow ou deleteRow sejam chamados.

Após uma chamada para atualizar<Type>, a coluna afetada não pode ser acessada pelo get<Type> até que updateRow ou cancelRowUpdates tenha sido chamado. Este comportamento evita problemas em que uma coluna é atualizada usando um tipo diferente do tipo devolvido pelo servidor, e chamadas getter subsequentes podem provocar conversões de tipo do lado do cliente que produzem resultados imprecisos. Chamadas para obter<Type> lançam uma exceção com a mensagem: "As colunas atualizadas não podem ser acedidas até que updateRow() ou cancelRowUpdates() tenham sido chamadas."

Observação

Caso o método updateRow seja chamado quando nenhuma coluna tiver sido atualizada, o driver JDBC lançará uma exceção com a mensagem, "updateRow() chamado quando nenhuma coluna foi atualizada."

Depois que moveToInsertRow for chamado, uma exceção será lançada se qualquer método, exceto get<Type>, update<Type>, insertRow e os métodos de posicionamento do cursor (incluindo moveToCurrentRow), for chamado no conjunto de resultados. O método moveToInsertRow coloca efetivamente o conjunto de resultados em modo de inserção, e os métodos de posicionamento do cursor terminam o modo de inserção. As chamadas de posicionamento relativo do cursor movem o cursor em relação à posição em que estava antes de ser chamado o método moveToInsertRow. Após chamadas de posicionamento do cursor, a posição final do cursor de destino torna-se a nova posição do cursor.

Se a chamada de posicionamento do cursor feita em modo de inserção não tiver sucesso, a posição do cursor após a chamada falhada é a posição original antes de moverToInsetRow ser chamado. Se o insertRow falhar, o cursor permanece na linha de inserção e o cursor permanece em modo de inserção.

As colunas na linha de inserção estão inicialmente num estado não inicializado. As chamadas ao método update<Type> definem o estado da coluna para inicializado. Uma chamada ao método get<Type> para uma coluna não inicializada lança uma exceção. Uma chamada ao método insertRow devolve todas as colunas da linha inserida a um estado não inicializado.

Se alguma coluna estiver sem inicializar quando o método insertRow é chamado, insere-se o valor padrão da coluna. Se não houver valor padrão mas a coluna for nullável, então NULL é inserido. Se não houver valor padrão e a coluna não for anulável, o servidor devolverá um erro e uma exceção será gerada.

Observação

As chamadas ao método getRow retornam 0 quando estão em modo de inserção.

O driver JDBC não suporta atualizações ou eliminações posicionadas. De acordo com a especificação JDBC, o método setCursorName não tem efeito e o método getCursorName lançará uma exceção se for chamado.

Cursores apenas de leitura e estáticos nunca são atualizáveis.

O SQL Server restringe os cursores do servidor a um único conjunto de resultados. Se um procedimento em lote ou armazenado contiver múltiplas instruções, então deve ser usado um cursor cliente apenas de leitura para frente.