Cursor (bancos de dados) - Cursor (databases)

Em ciência da computação , um banco de dados cursor é uma estrutura de controle que permite travessia ao longo dos registros em um banco de dados. Os cursores facilitam o processamento subsequente em conjunto com a travessia, como recuperação, adição e remoção de registros do banco de dados. A característica do cursor de banco de dados de travessia torna os cursores semelhantes ao conceito de iterador da linguagem de programação .

Os cursores são usados ​​por programadores de banco de dados para processar linhas individuais retornadas por consultas do sistema de banco de dados . Os cursores permitem a manipulação de conjuntos de resultados inteiros de uma vez. Nesse cenário, um cursor permite o processamento sequencial de linhas em um conjunto de resultados.

Em procedimentos SQL, um cursor torna possível definir um conjunto de resultados (um conjunto de linhas de dados) e executar lógica complexa linha por linha. Usando a mesma mecânica, um procedimento SQL também pode definir um conjunto de resultados e retorná-lo diretamente para o chamador do procedimento SQL ou para um aplicativo cliente.

Um cursor pode ser visto como um ponteiro para uma linha em um conjunto de linhas. O cursor só pode fazer referência a uma linha por vez, mas pode mover-se para outras linhas do conjunto de resultados conforme necessário.

Uso

Para usar cursores em procedimentos SQL, você precisa fazer o seguinte:

  1. Declare um cursor que define um conjunto de resultados.
  2. Abra o cursor para estabelecer o conjunto de resultados.
  3. Busque os dados em variáveis ​​locais conforme necessário do cursor, uma linha por vez.
  4. Feche o cursor quando terminar.

Para trabalhar com cursores, você deve usar as seguintes instruções SQL

Esta seção apresenta as maneiras como o padrão SQL: 2003 define como usar cursores em aplicativos em SQL embutido. Nem todas as ligações de aplicativo para sistemas de banco de dados relacional seguem esse padrão e algumas (como CLI ou JDBC ) usam uma interface diferente.

Um programador torna um cursor conhecido no SGBD usando uma instrução DECLARE... CURSORe atribuindo ao cursor um nome (obrigatório):

 DECLARE cursor_name CURSOR IS SELECT ... FROM ...

Antes que o código possa acessar os dados, ele deve abrir o cursor com a OPENinstrução. Logo após uma abertura bem-sucedida, o cursor é posicionado antes da primeira linha no conjunto de resultados.

 OPEN cursor_name

Os aplicativos posicionam os cursores em uma linha específica no conjunto de resultados com a FETCHinstrução. Uma operação de busca transfere os dados da linha para o aplicativo.

 FETCH cursor_name INTO ...

Depois que um aplicativo processou todas as linhas disponíveis ou a operação de busca deve ser posicionada em uma linha não existente (compare os cursores roláveis abaixo), o DBMS retorna um SQLSTATE '02000' (geralmente acompanhado por um SQLCODE +100) para indicar o fim do conjunto de resultados.

A etapa final envolve fechar o cursor usando a CLOSEinstrução:

 CLOSE cursor_name

Depois de fechar um cursor, um programa pode abri-lo novamente, o que implica que o SGBD reavalia a mesma consulta ou uma consulta diferente e constrói um novo conjunto de resultados.

Cursores roláveis

Os programadores podem declarar cursores como roláveis ​​ou não roláveis. A capacidade de rolagem indica a direção na qual um cursor pode se mover.

Com um cursor não rolável (ou somente para frente ), você pode FETCHacessar cada linha no máximo uma vez, e o cursor se moverá automaticamente para a próxima linha. Depois de buscar a última linha, se buscar novamente, você colocará o cursor após a última linha e obterá o seguinte código: SQLSTATE 02000 (SQLCODE +100).

Um programa pode posicionar um cursor rolável em qualquer lugar no conjunto de resultados usando a FETCHinstrução SQL. A palavra-chave SCROLL deve ser especificada ao declarar o cursor. O padrão é NO SCROLL, embora diferentes ligações de linguagem como JDBC possam aplicar um padrão diferente.

 DECLARE cursor_name sensitivity SCROLL CURSOR FOR SELECT ... FROM ...

A posição de destino para um cursor rolável pode ser especificada relativamente (a partir da posição atual do cursor) ou absolutamente (a partir do início do conjunto de resultados).

 FETCH [ NEXT | PRIOR | FIRST | LAST ] FROM cursor_name
 FETCH ABSOLUTE n FROM cursor_name
 FETCH RELATIVE n FROM cursor_name;

Cursores roláveis ​​podem potencialmente acessar a mesma linha no conjunto de resultados várias vezes. Portanto, modificações de dados (operações de inserção, atualização, exclusão) de outras transações podem afetar o conjunto de resultados. Um cursor pode ser SENSÍVEL ou INSENSÍVEL a tais modificações de dados. Um cursor sensível seleciona modificações de dados que afetam o conjunto de resultados do cursor, e um cursor insensível não. Além disso, um cursor pode ser INSENSÍVEL e, nesse caso, o DBMS tenta aplicar a sensibilidade o máximo possível.

"COM ESPERA"

Os cursores são normalmente fechados automaticamente no final de uma transação, ou seja, quando ocorre um COMMIT ou ROLLBACK (ou um encerramento implícito da transação). Esse comportamento pode ser alterado se o cursor for declarado usando a cláusula WITH HOLD (o padrão é WITHOUT HOLD). Um cursor que pode ser mantido é mantido aberto sobre COMMIT e fechado sobre ROLLBACK. (Alguns SGBD desviam deste comportamento padrão e também mantêm cursores fixáveis ​​abertos em ROLLBACK.)

 DECLARE  cursor_name CURSOR  WITH HOLD  FOR SELECT .... FROM ....

Quando ocorre um COMMIT, um cursor que pode ser mantido é posicionado antes da próxima linha. Portanto, uma instrução UPDATE ou DELETE posicionada só terá êxito depois que uma operação FETCH ocorrer primeiro na transação.

Observe que o JDBC define os cursores como seguráveis ​​por padrão. Isso é feito porque o JDBC também ativa a confirmação automática por padrão.

Instruções de atualização / exclusão posicionadas

Os cursores podem ser usados ​​não apenas para buscar dados do DBMS em um aplicativo, mas também para identificar uma linha em uma tabela a ser atualizada ou excluída. O padrão SQL: 2003 define as instruções SQL de atualização posicionada e exclusão posicionada para esse propósito. Essas instruções não usam uma cláusula WHERE regular com predicados. Em vez disso, um cursor identifica a linha. O cursor deve estar aberto e já posicionado em uma linha por meio de FETCHdeclaração.

 UPDATE table_name
 SET    ...
 WHERE  CURRENT OF cursor_name
 DELETE
 FROM   table_name
 WHERE  CURRENT OF cursor_name

O cursor deve operar em um conjunto de resultados atualizáveis ​​para executar com êxito uma atualização posicionada ou instrução de exclusão. Caso contrário, o DBMS não saberia como aplicar as alterações de dados às tabelas subjacentes referidas no cursor.

Cursores em transações distribuídas

Usar cursores em transações distribuídas (ambientes X / Open XA ), que são controlados por meio de um monitor de transação, não é diferente de cursores em transações não distribuídas.

É preciso prestar atenção ao usar cursores sustentáveis , entretanto. As conexões podem ser usadas por diferentes aplicativos. Portanto, uma vez que uma transação foi finalizada e confirmada, uma transação subsequente (em execução em um aplicativo diferente) pode herdar os cursores existentes. Portanto, um desenvolvedor de aplicativos deve estar ciente dessa situação.

Cursores em XQuery

A linguagem XQuery permite que cursores sejam criados usando a função subsequence () .

O formato é:

let $displayed-sequence := subsequence($result, $start, $item-count)

Onde $ result é o resultado da XQuery inicial, $ start é o número do item a ser iniciado e $ item-count é o número de itens a serem retornados.

De forma equivalente, isso também pode ser feito usando um predicado:

let $displayed-sequence := $result[$start to $end]

Onde $endestá a seqüência final.

Para exemplos completos, consulte XQuery / Searching, Paging and Sorting # Paging em Wikibooks.

Desvantagens dos cursores

As informações a seguir podem variar dependendo do sistema de banco de dados específico.

Buscar uma linha do cursor pode resultar em uma viagem de ida e volta da rede a cada vez. Isso usa muito mais largura de banda da rede do que normalmente seria necessário para a execução de uma única instrução SQL como DELETE. As viagens de ida e volta repetidas na rede podem reduzir drasticamente a velocidade da operação usando o cursor. Alguns DBMSs tentam reduzir esse efeito usando a busca de bloco. A busca de bloco implica que várias linhas são enviadas juntas do servidor para o cliente. O cliente armazena um bloco inteiro de linhas em um buffer local e recupera as linhas de lá até que o buffer se esgote.

Os cursores alocam recursos no servidor, como bloqueios , pacotes, processos e armazenamento temporário. Por exemplo, o Microsoft SQL Server implementa cursores criando uma tabela temporária e preenchendo-a com o conjunto de resultados da consulta. Se um cursor não for fechado corretamente ( desalocado ), os recursos não serão liberados até que a própria sessão SQL (conexão) seja fechada. Esse desperdício de recursos no servidor pode levar à degradação do desempenho e falhas.

Exemplo

TABELA DE FUNCIONÁRIOS

SQL> desc EMPLOYEES_DETAILS;
 Name                                      Null?    Type
 ----------------------------------------- -------- --------------------

 EMPLOYEE_ID                               NOT NULL NUMBER(6)
 FIRST_NAME                                         VARCHAR2(20)
 LAST_NAME                                 NOT NULL VARCHAR2(25)
 EMAIL                                     NOT NULL VARCHAR2(30)
 PHONE_NUMBER                                       VARCHAR2(20)
 HIRE_DATE                                 NOT NULL DATE
 JOB_ID                                    NOT NULL VARCHAR2(10)
 SALARY                                             NUMBER(8,2)
 COMMISSION_PCT                                     NUMBER(2,2)
 MANAGER_ID                                         NUMBER(6)
 DEPARTMENT_ID                                      NUMBER(4)
SAMPLE CURSOR KNOWN AS EE

CREATE OR REPLACE 
PROCEDURE EE AS
BEGIN

DECLARE
	v_employeeID EMPLOYEES_DETAILS.EMPLOYEE_ID%TYPE;
	v_FirstName EMPLOYEES_DETAILS.FIRST_NAME%TYPE;
	v_LASTName EMPLOYEES_DETAILS.LAST_NAME%TYPE;
	v_JOB_ID EMPLOYEES_DETAILS.JOB_ID%TYPE:= 'IT_PROG';

Cursor c_EMPLOYEES_DETAILS IS
	SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME
	FROM EMPLOYEES_DETAILS
	WHERE JOB_ID ='v_JOB_ID';

BEGIN
	OPEN c_EMPLOYEES_DETAILS;

	LOOP

		FETCH c_EMPLOYEES_DETAILS INTO v_employeeID,v_FirstName,v_LASTName;

		DBMS_OUTPUT.put_line(v_employeeID);
		DBMS_OUTPUT.put_line(v_FirstName);
		DBMS_OUTPUT.put_line(v_LASTName);

		EXIT WHEN c_EMPLOYEES_DETAILS%NOTFOUND;
	END LOOP;

	CLOSE c_EMPLOYEES_DETAILS;
END;

END;

Veja também

Referências

  • Christopher J. Date : Database in Depth , O'Reilly & Associates, ISBN  0-596-10012-4
  • Thomas M. Connolly , Carolyn E. Begg : Database Systems , Addison-Wesley, ISBN  0-321-21025-5
  • Ramiz Elmasri , Shamkant B. Navathe : Fundamentals of Database Systems , Addison-Wesley, ISBN  0-201-54263-3
  • Neil Matthew , Richard Stones : Beginning Databases with PostgreSQL: From Novice to Professional , Apress, ISBN  1-59059-478-9
  • Thomas Kyte : Expert One-On-One: Oracle , Apress, ISBN  1-59059-525-4
  • Kevin Loney: Oracle Database 10g: The Complete Reference , Oracle Press, ISBN  0-07-225351-7

links externos