DECLARE — define um cursor
DECLAREnome[ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ] FORconsulta
O comando DECLARE permite que o usuário crie
cursores, que podem ser usados para recuperar um pequeno número
de linhas por vez de uma consulta maior.
Após o cursor ser criado, as linhas são buscadas usando o comando
FETCH.
Esta página descreve o uso de cursores no nível de comando SQL. Caso se esteja tentando usar cursores numa função escrita em PL/pgSQL, as regras são diferentes — veja Seção 41.7.
nomeO nome do cursor a ser criado. Este nome deve ser diferente de qualquer outro nome de cursor ativo na sessão.
BINARYFaz com que o cursor retorne os dados no formato binário, em vez de no formato texto.
ASENSITIVEINSENSITIVE
A sensibilidade do cursor determina se as alterações nos dados
subjacentes ao cursor, feitas na mesma transação, após o cursor
ser declarado, são visíveis ao cursor.
INSENSITIVE significa que não são visíveis,
ASENSITIVE significa que o comportamento
depende da implementação.
Um terceiro comportamento, SENSITIVE, que
significa que estas mudanças são visíveis ao cursor, não está
disponível no PostgreSQL.
No PostgreSQL, todos os cursores são
insensíveis; portanto, estas palavras-chave não têm efeito,
sendo aceitas apenas para manter a compatibilidade com o padrão
SQL.
Especificar INSENSITIVE junto com
FOR UPDATE ou FOR SHARE,
é um erro.
SCROLLNO SCROLL
SCROLL (rolagem) especifica que o cursor pode
ser usado para recuperar linhas de maneira não sequencial
(por exemplo, para trás).
Dependendo da complexidade do plano de execução da consulta,
especificar SCROLL pode impor uma penalidade
de desempenho no tempo de execução da consulta.
NO SCROLL especifica que o cursor não pode ser
usado para recuperar linhas de maneira não sequencial.
O padrão é permitir a rolagem em alguns casos;
não é o mesmo que especificar SCROLL.
Veja Notas para obter detalhes.
WITH HOLDWITHOUT HOLD
WITH HOLD especifica que o cursor pode
continuar sendo usado após a transação que o criou ser efetivada
(commited) com sucesso.
WITHOUT HOLD especifica que o cursor não pode
ser usado fora da transação que o criou.
Se não for especificado nem WITHOUT HOLD ou
WITH HOLD, o padrão será
WITHOUT HOLD.
consultaUm comando SELECT ou VALUES que fornece as linhas a serem retornadas pelo cursor.
As palavras-chave ASENSITIVE,
BINARY, INSENSITIVE, e
SCROLL podem aparecer em qualquer ordem.
Os cursores normais retornam dados no formato texto,
o mesmo que o comando SELECT produz.
A opção BINARY especifica que o cursor deve
retornar os dados no formato binário.
Isto reduz o esforço de conversão, tanto para o servidor quanto para
o cliente, ao custo de mais esforço do programador para lidar com
formatos de dados binários dependentes de plataforma.
Por exemplo, se uma consulta retornar o valor “um”
de uma coluna inteira, será obtida uma cadeia de caracteres contendo
1 com o cursor padrão, enquanto com um cursor
binário será obtido um campo de 4 bytes contendo a representação
interna do valor (na ordem de bytes
big-endian).
Os cursores binários devem ser usados com cuidado. Muitas aplicações, incluindo o psql, não estão preparadas para lidar com cursores binários, esperando que os dados retornem no formato texto.
Quando a aplicação cliente usa o protocolo de
“consulta estendida”
(extended query)
para enviar o comando FETCH, a mensagem
Bind do protocolo especifica se os
dados devem ser retornados no formato texto ou binário.
Esta escolha se sobrepõe ao modo como o cursor foi definido.
O conceito de cursor binário como tal é, portanto, obsoleto ao
usar o protocolo de consulta estendida — qualquer cursor pode
ser tratado como texto ou binário.
A menos que seja especificado WITH HOLD, o cursor
criado por este comando só poderá ser usado dentro da transação corrente.
Assim, DECLARE sem WITH HOLD
é inútil fora de um bloco de transação: o cursor sobreviveria apenas
até o término da instrução.
Portanto, o PostgreSQL irá relatar um
erro se este comando for usado fora de um bloco de transação.
Deve ser usado BEGIN e
COMMIT (ou ROLLBACK)
para definir um bloco de transação.
Se for especificado WITH HOLD, e a transação que
criou o cursor for efetivada com sucesso, o cursor poderá continuar
sendo acessado por transações subsequentes na mesma sessão.
(Mas se a transação que criou o cursor for interrompida, o cursor
será removido.)
Um cursor criado com WITH HOLD é fechado por uma
instrução CLOSE explícita para ele, ou quando
a sessão termina.
Na implementação corrente, as linhas representadas por um cursor
persistente (WITH HOLD) são copiadas para um
arquivo temporário, ou área de memória, para permanecerem
disponíveis para as transações subsequentes.
WITH HOLD não pode ser especificado quando a
consulta inclui FOR UPDATE ou
FOR SHARE.
A opção SCROLL deve ser especificada ao definir
um cursor que será usado para buscar para trás.
Isto é requerido pelo padrão SQL.
Entretanto, para manter a compatibilidade com versões anteriores, o
PostgreSQL permitirá buscas para trás sem
SCROLL, se o plano de consulta do cursor for
simples o suficiente para que nenhuma sobrecarga extra seja
necessária para suportá-lo.
Porém, os desenvolvedores de aplicações são aconselhados a não
confiar no uso de buscas para trás em um cursor que não tenha sido
criado com SCROLL.
Se for especificado NO SCROLL, as buscas para
trás não serão permitidas em nenhum caso.
Buscas para trás também não são permitidas quando a consulta inclui
FOR UPDATE ou FOR SHARE;
portanto SCROLL não pode ser especificado nesses
casos.
Os cursores roláveis podem fornecer resultados inesperados se
chamarem funções voláteis (veja Categorias de volatilidade da função).
Quando uma linha buscada anteriormente, é buscada novamente,
as funções podem ser executadas novamente, talvez levando a
resultados diferentes dos da primeira vez.
É melhor especificar NO SCROLL para consultas
envolvendo funções voláteis.
Se isto não for prático, uma solução alternativa é declarar o cursor
como SCROLL WITH HOLD, e efetivar a transação
antes de ler qualquer linha dele.
Isto irá fazer com que toda a saída do cursor seja materializada
no armazenamento temporário, para que as funções voláteis sejam
executadas exatamente uma vez para cada linha.
Se a consulta do cursor incluir FOR UPDATE ou
FOR SHARE, as linhas retornadas serão bloqueadas
no momento em que forem buscadas pela primeira vez, da mesma forma
que para um comando SELECT regular com
estas opções.
Além disso, as linhas retornadas serão as versões mais atualizadas.
Geralmente é recomendado o uso de FOR UPDATE
se o cursor se destina a ser usado com
UPDATE ... WHERE CURRENT OF. ou
DELETE ... WHERE CURRENT OF.
Usar FOR UPDATE evita que outras sessões alterem
as linhas entre a hora em que são buscadas e a hora em que são
atualizadas.
Sem FOR UPDATE, um comando
WHERE CURRENT OF subsequente não terá efeito,
se a linha tiver sido alterada depois que o cursor foi criado.
Outra razão para usar FOR UPDATE é que sem ele,
um WHERE CURRENT OF subsequente poderá falhar
se a consulta do cursor não atender às regras do padrão
SQL para ser
“atualizável de forma simples”
(simply updatable)
(em particular, o cursor deve referenciar apenas uma tabela,
todas as colunas do resultado serem atualizáveis,
e não usar agrupamento ou ORDER BY).
Os cursores que não são atualizáveis de forma simples podem
funcionar ou não, dependendo dos detalhes da escolha do plano;
portanto, na pior das hipóteses, uma aplicação pode funcionar no
teste e falhar em produção.
Se for especificado FOR UPDATE, há garantia de
que o cursor será atualizável.
O principal motivo para não usar FOR UPDATE com
WHERE CURRENT OF é quando se necessita que o
cursor seja rolável, ou isolado de atualizações simultâneas
(ou seja, continue a mostrar os dados antigos).
Se isto for um requisito, deve-se prestar muita atenção às
advertências mostradas acima.
O padrão SQL faz apenas provisões para cursores
em SQL incorporado.
O servidor PostgreSQL não implementa a
instrução OPEN para cursores;
o cursor é considerado aberto quando é declarado.
Entretanto, o ECPG — Embedded SQL in C, o pré-processador para
SQL incorporado do
PostgreSQL,
fornece suporte às convenções de cursor do padrão
SQL, incluindo as que envolvem as instruções
DECLARE e OPEN.
A estrutura de dados do servidor subjacente a um cursor aberto
é chamada de portal.
Os nomes dos portais são expostos no protocolo do cliente:
um cliente pode buscar linhas diretamente de um portal aberto,
se souber o nome do portal.
Ao criar um cursor com o comando DECLARE,
o nome do portal é o mesmo que o nome do cursor.
Podem ser vistos todos os cursores disponíveis consultando a visão do sistema pg_cursors.
Para declarar um cursor:
DECLARE liahona CURSOR FOR SELECT * FROM films;
Veja o comando FETCH para obter mais exemplos de uso de cursor.
O padrão SQL permite cursores apenas em SQL incorporado e em módulos. O PostgreSQL permite que os cursores sejam usados interativamente.
Segundo o padrão SQL, as alterações feitas
em cursores insensíveis por instruções
UPDATE ... WHERE CURRENT OF e
DELETE ... WHERE CURRENT OF
são visíveis neste mesmo cursor.
O PostgreSQL trata estas instruções como
as demais instruções de alteração de dados, porque também não são
visíveis em cursores insensíveis.
Os cursores binários são uma extensão do PostgreSQL.
As informações sobre os cursores disponíveis no momento podem ser consultadas através da visão do sistema pg_cursors.