Noções básicas sobre tipos de cursor
As operações em um ato de banco de dados relacional em um conjunto completo de linhas. O conjunto de linhas retornado por uma instrução SELECT consiste em todas as linhas que satisfazem as condições na cláusula WHERE da instrução. Este conjunto completo de linhas retornado pela instrução é conhecido como conjunto de resultados. Nem sempre os aplicativos podem trabalhar efetivamente com o conjunto de resultados inteiro como uma unidade. Esses aplicativos precisam de um mecanismo para trabalhar com uma linha ou um bloco pequeno de linhas de cada vez. Os cursores são uma extensão dos conjuntos de resultados que proveem esse mecanismo.
Os cursores estendem o processamento do conjunto de resultados fazendo o seguinte:
- Permitirem o posicionamento em linhas específicas do conjunto de resultados.
- Recuperarem uma linha ou bloco de linhas de posições atuais em um conjunto de resultados.
- Oferecendo suporte a modificações de dados na linha da posição atual no conjunto de resultados.
- São compatíveis com diferentes níveis de visibilidade das mudanças feitas por outros usuários nos dados do banco de dados que são apresentados no conjunto de resultados.
Observação
Para uma descrição completa dos tipos de cursor do SQL Server, confira Tipos de Cursores.
A especificação do JDBC provê suporte para cursores somente encaminhamento e roláveis que são sensíveis ou insensíveis a alterações feitas por outros trabalhos e podem ser somente leitura ou atualizáveis. Essa funcionalidade é fornecida pela classe Microsoft JDBC Driver para SQL ServerSQLServerResultSet.
Comentários
O driver JDBC é compatível com o seguinte conjunto de resultados e tipos de cursor, juntamente com as opções de comportamento especificadas.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) | N/D | Somente encaminhamento, somente leitura | direct | completa |
O aplicativo tem que fazer uma única passagem (para a frente) pelo conjunto de resultados. Essa passagem é o comportamento padrão, que é o mesmo de um cursor TYPE_SS_DIRECT_FORWARD_ONLY. O driver lê o conjunto de resultados inteiro do servidor em uma memória durante o tempo de execução da instrução.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) | N/D | Somente encaminhamento, somente leitura | direct | adaptive |
O aplicativo tem que fazer uma única passagem (para a frente) pelo conjunto de resultados. O comportamento é igual ao de um cursor TYPE_SS_DIRECT_FORWARD_ONLY. O driver lê as linhas do servidor à medida que o aplicativo as solicita e assim minimiza o uso de memória do lado do cliente.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) | Avanço rápido | Somente encaminhamento, somente leitura | cursor | N/D |
O aplicativo tem que fazer uma única passagem (para a frente) pelo conjunto de resultados usando um cursor de servidor. O comportamento é igual ao de um cursor TYPE_SS_SERVER_CURSOR_FORWARD_ONLY.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_FORWARD_ONLY (CONCUR_UPDATABLE) | Dinâmico (somente encaminhamento) | Somente encaminhamento, atualizável | N/D | N/D |
O aplicativo tem que 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 da busca.
Por padrão, o tamanho da busca é fixado quando o aplicativo chama o método setFetchSize do objeto SQLServerResultSet.
Observação
o JDBC Driver fornece um recurso de buffer adaptável que permite recuperar resultados da execução de instruções do SQL Server à medida que o aplicativo precisar deles, e não tudo de uma vez. Por exemplo, se o aplicativo precisar recuperar um volume de dados grande demais para caber inteiramente na memória do aplicativo, o buffer adaptável permitirá que o aplicativo cliente recupere esse valor como um fluxo. O comportamento padrão do driver é "adaptável". No entanto, a fim de obter o buffer adaptável para os conjuntos de resultados atualizáveis de somente avanço, o aplicativo precisa chamar explicitamente o método setResponseBuffering do objeto SQLServerStatement fornecendo um valor de String "adaptável". Para ver um exemplo de código, confira Atualizar um exemplo de dados grandes.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SCROLL_INSENSITIVE | Estático | Rolável, não atualizável. Atualizações, inserções e exclusões de linhas externas não são visíveis. |
N/D | N/D |
O aplicativo requer um instantâneo do banco de dados. O conjunto de resultados não é atualizável. Só há suporte para CONCUR_READ_ONLY. Todos os outros tipos de simultaneidade causarão uma exceção quando usados com este tipo de cursor.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SCROLL_SENSITIVE (CONCUR_READ_ONLY) | Keyset | Com rolagem, somente leitura. As atualizações de linhas externas são visíveis, e as exclusões aparecem como dados ausentes. As inserções de linhas externas não são visíveis. |
N/D | N/D |
O aplicativo tem que ver dados alterados somente para linhas existentes.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SCROLL_SENSITIVE (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) | Keyset | Rolável, atualizável. As atualizações de linhas externas e internas são visíveis, e as exclusões aparecem como dados ausentes; as inserções não são visíveis. |
N/D | N/D |
O aplicativo pode alterar dados nas linhas existentes usando o objeto ResultSet. O aplicativo também precisa ser capaz de ver as alterações em linhas feitas por outros de fora do objeto ResultSet.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SS_DIRECT_FORWARD_ONLY | N/D | Somente encaminhamento, somente leitura | N/D | completo ou adaptável |
Valor inteiro = 2003. Fornece um cursor somente leitura do lado do cliente que é totalmente armazenado em buffer. Nenhum cursor de servidor é criado.
Só há suporte para o tipo de simultaneidade CONCUR_READ_ONLY. Todos os outros tipos de simultaneidade causarão uma exceção quando usados com este tipo de cursor.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SS_SERVER_CURSOR_FORWARD_ONLY | Avanço rápido | Somente avanço | N/D | N/D |
Valor inteiro = 2004. Rápido, acessa todos os dados usando um cursor de servidor. É atualizável quando usado com o tipo de simultaneidade CONCUR_UPDATABLE.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Para obter o buffer adaptável para este caso, o aplicativo tem que chamar explicitamente o método setResponseBuffering do objeto SQLServerStatement fornecendo o valor String de "adaptive" . Para ver um exemplo de código, confira Atualizar um exemplo de dados grandes.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SS_SCROLL_STATIC | Estático | As atualizações de outros usuários não são refletidas. | N/D | N/D |
Valor inteiro = 1004. O aplicativo requer um instantâneo do banco de dados. Essa opção é o sinônimo específico do SQL Server para o TYPE_SCROLL_INSENSITIVE do JDBC e tem o mesmo comportamento de configuração de simultaneidade.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SS_SCROLL_KEYSET (CONCUR_READ_ONLY) | Keyset | Com rolagem, somente leitura. As atualizações de linhas externas são visíveis, e as exclusões aparecem como dados ausentes. As inserções de linhas externas não são visíveis. |
N/D | N/D |
Valor inteiro = 1005. O aplicativo tem que ver dados alterados somente para linhas existentes. Essa opção é o sinônimo específico do SQL Server para o TYPE_SCROLL_SENSITIVE do JDBC e tem o mesmo comportamento de configuração de simultaneidade.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SS_SCROLL_KEYSET (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) | Keyset | Rolável, atualizável. As atualizações de linhas externas e internas são visíveis, e as exclusões aparecem como dados ausentes; as inserções não são visíveis. |
N/D | N/D |
Valor inteiro = 1005. O aplicativo tem que alterar dados ou ver dados alterados para linhas existentes. Essa opção é o sinônimo específico do SQL Server para o TYPE_SCROLL_SENSITIVE do JDBC e tem o mesmo comportamento de configuração de simultaneidade.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SS_SCROLL_DYNAMIC (CONCUR_READ_ONLY) | Dinâmico | Com rolagem, somente leitura. As atualizações e as inserções de linhas externas são visíveis, e as exclusões aparecem como dados ausentes transitórios no buffer de busca atual. |
N/D | N/D |
Valor inteiro = 1006. O aplicativo deve ver dados alterados para linhas existentes, além de ver linhas inseridas e excluídas durante o tempo de vida do cursor.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Tipo do conjunto de resultados (cursor) | Tipo de cursor do SQL Server | Características | Método de seleção | Buffer de resposta |
---|---|---|---|---|
TYPE_SS_SCROLL_DYNAMIC (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) | Dinâmico | Rolável, atualizável. As atualizações e as inserções de linhas externas e internas são visíveis, e as exclusões aparecem como dados ausentes transitórios no buffer de busca atual. |
N/D | N/D |
Valor inteiro = 1006. O aplicativo pode alterar dados para linhas existentes, inserir ou excluir linhas usando o objeto ResultSet. O aplicativo também precisa ser capaz de ver as alterações, inserções e exclusões feitas por outros de fora do objeto ResultSet.
As linhas são recuperadas do servidor em blocos especificados pelo tamanho da busca.
Posicionamento dos cursores
Os cursores TYPE_FORWARD_ONLY, TYPE_SS_DIRECT_FORWARD_ONLY e TYPE_SS_SERVER_CURSOR_FORWARD_ONLY são compatíveis apenas com método de posicionamento next.
O cursor TYPE_SS_SCROLL_DYNAMIC não é compatível com os métodos absolute e getRow. O método absoluto pode ser aproximado por uma combinação de chamadas para os métodos first e relative para cursores dinâmicos.
O método getRow só é compatível com os 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 de somente avanço retorna o número de linhas lidas até o momento por meio do cursor.
Observação
Quando um aplicativo faz uma chamada de posicionamento de cursor não compatível ou uma chamada não compatível para o método getRow, uma exceção é lançada com a mensagem "A operação solicitada não é compatível com esse tipo de cursor."
Só o cursor TYPE_SS_SCROLL_KEYSET e o TYPE_SCROLL_SENSITIVE equivalente expõem linhas excluídas. Se o cursor for posicionado em uma linha excluída, os valores de coluna não estarão disponíveis e o método rowDeleted retornará "true". As chamadas para os métodos get<Type> lançam uma exceção com a mensagem "Não é possível obter um valor de uma linha excluída". As linhas excluídas não podem ser atualizadas. Se você tentar chamar um método update<Type> em uma linha excluída, uma exceção será lançada com a mensagem "Uma linha excluída 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.
Os cursores dinâmicos e de avançar expõem as linhas excluídas de modo semelhante, mas só enquanto permanecem acessíveis no buffer de busca. No caso dos cursores de avanço, esse comportamento é razoavelmente simples. No caso dos cursores dinâmicos, é mais complexo quando o tamanho da busca é maior que 1. Um aplicativo pode mover o cursor para a frente e para trás dentro da janela definida pelo buffer de busca, mas a linha excluída desaparecerá quando a ação sair do buffer de busca original no qual ocorreu a atualização. Se um aplicativo não desejar ver as linhas excluídas transitórias usando cursores dinâmicos, deverá ser usado um relativo de busca (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 reterá sua posição original no conjunto de resultados, quer a linha atualizada atenda ou não aos critérios de seleção do cursor. Se a linha foi atualizada fora do cursor, uma linha excluída aparecerá na posição original da linha, mas a linha só aparecerá no cursor se outra linha com os novos valores-chave estava presente no cursor, mas foi excluída subsequentemente.
Para cursores dinâmicos, as linhas atualizadas reterão a posição dentro do buffer de busca até que a ação saia da janela definida pelo buffer de busca. Linhas atualizadas podem reaparecer posteriormente em posições diferentes dentro do conjunto de resultados ou podem desaparecer completamente. Os aplicativos que precisam evitar inconsistências transitórias no conjunto de resultados devem usar um tamanho de busca igual a 1 (o padrão é 8 linhas com simultaneidade de CONCUR_SS_SCROLL_LOCKS e 128 linhas com outras simultaneidades).
Conversão de cursores
Às vezes, o SQL Server pode escolher implementar um tipo de cursor diferente do solicitado, circunstância conhecida como conversão implícita de cursor (ou degradação de cursor).
Com o SQL Server 2000 (8.x), quando você atualiza os dados pelo conjunto de resultados ResultSet.TYPE_SCROLL_SENSITIVE e ResultSet.CONCUR_UPDATABLE, uma exceção é lançada com a mensagem "O cursor é READ ONLY". Essa 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 retornou o cursor atualizável solicitado.
Para solucionar esse problema, use uma das soluções a seguir:
- Verifique se a tabela subjacente tem uma chave primária
- Use SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC em vez de ResultSet.TYPE_SCROLL_SENSITIVE enquanto cria uma instrução.
Atualização de cursores
Há suporte para atualizações in-loco de cursores nos casos em que a simultaneidade e o tipo do cursor oferecem suporte a atualizações. Se o cursor não estiver posicionado em uma linha atualizável no conjunto de resultados (nenhuma chamada de método get<Type> foi bem-sucedida), uma chamada para um método update<Type> lançará uma exceção com a mensagem: "O conjunto de resultados não tem nenhuma linha atual". A especificação JDBC afirma que uma exceção surge 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, por exemplo, por causa de um conflito de simultaneidade otimista como uma atualização ou exclusão concorrente, a exceção poderá não ocorrer até que o método insertRow, updateRow ou deleteRow seja chamado.
Depois de uma chamada para update<Type>, a coluna afetada não poderá ser acessada por get<Type> até que updateRow ou cancelRowUpdates seja chamado. Esse comportamento evita problemas em que uma coluna é atualizada usando um tipo diferente do tipo retornado pelo servidor, e chamadas do método getter subsequentes poderiam invocar conversões de tipo do lado do cliente com resultados inexatos. Chamadas para get<Type> lançarão uma exceção com a mensagem "Não é possível acessar as colunas atualizadas até que updateRow() ou cancelRowUpdates() seja chamado".
Observação
Se o método updateRow for 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 que não seja get<Type>, update<Type>, insertRow e os métodos de posicionamento do cursor (inclusive moveToCurrentRow) for chamado no conjunto de resultados. O método moveToInsertRow coloca o conjunto de resultados efetivamente no 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 ele se encontrava antes de moveToInsertRow ser chamado. Após chamadas de posicionamento do cursor, a futura posição de destino do cursor se torna a nova posição do cursor.
Se a chamada de posicionamento do cursor feita no modo de inserção não for bem-sucedida, a posição do cursor após a chamada com falha será a posição original do cursor antes de moveToInsetRow ser chamado. Se ocorrer falha em insertRow, o cursor permanecerá na linha de inserção e no modo de inserção.
As colunas na linha de inserção estão inicialmente em um estado não inicializado. As chamadas para o método update<Type> definem o estado de coluna como inicializado. Uma chamada para o método get<Type> para uma coluna não inicializada lança uma exceção. Uma chamada para o método insertRow retorna todas as colunas na linha de inserção para um estado não inicializado.
Se uma coluna estiver no estado não inicializado quando o método insertRow for chamado, será inserido o valor padrão da coluna. Se não houver um valor padrão, mas a coluna for anulável, NULL será inserido. Se não houver um valor padrão e a coluna não for anulável, o servidor retornará um erro e uma exceção será lançada.
Observação
As chamadas para o método getRow retornam 0 no modo de inserção.
O driver JDBC não oferece suporte a atualizações ou exclusões posicionadas. De acordo com a especificação do JDBC, o método setCursorName não tem nenhum efeito e o método getCursorName lançará uma exceção se for chamado.
Os cursores somente leitura e estáticos nunca são atualizáveis.
O SQL Server restringe os cursores de servidor a um único conjunto de resultados. Se um procedimento em lote ou armazenado contiver várias instruções, um cursor de cliente somente encaminhamento e somente leitura deverá ser usado.