Você está na página 1de 7

Laboratrio de Banco de Dados II Cursor em Bancos de dados

Cursor
Vamos entender o significado da estrutura de cursor em banco de dados atravs de um exemplo. Antes disso, vamos tratar da caracterstica da linguagem SQL. Diferentemente do que fazem as linguagens utilizadas para desenvolvimento de programas, que so voltadas para o tratamento individual de registros de um conjunto, a linguagem SQL voltada para o tratamento de conjuntos. No entanto, existem situaes em que voc gostaria de tratar, em SQL, no mbito do prprio banco de dados, cada uma das linhas de uma tabela ou de um conjunto de linhas resultante de uma operao, da mesma forma como numa linguagem de programao habitual.

Considere o problema abaixo proposto que consiste na obteno da classificao das cidades segundo a quantidade de habitantes.
codigo -------0002 0011 0013 0007 0008 0006 0009 0005 0004 0003 0012 0010 0001 0014 nome habitantes qtd_ruas estado classif_hab classif_ruas ----------------- ---------- -------- ------ ----------- -----------BRASILIA 300000 800 DF JK 40000 700 SP SEGUNDA_MENOR 20000 1500 RJ CEILANDIA 50000 1400 DF BRASLANDIA 30000 2500 DF SAO CARLOS 60000 500 SP MAUA 30000 1300 SP SAO CAETANO 40000 1500 SP SANTO ANDRE 300000 1400 SP TAGUATINGA 50000 1100 DF SEGUNDA_MAIOR 50000 300 RJ OSASCO 550000 800 SP SAO PAULO 9000000 14000 SP ABCDEF 800000 800 MG

Na figura, esto os dados de cidades com as respectivas quantidades de habitantes e ruas. A coluna de classificao no est preenchida. Suponha que a sua tarefa seja preench-la. No caso do exemplo, existe a possibilidade real de duas cidades terem a mesma quantidade de habitantes porque os dados so arredondados na casa de 104. Como fazer isto? Uma das formas percorrer seqencialmente a tabela em ordem crescente ou decrescente de nmero de habitantes e atribuir a classificao, com o cuidado de considerar a mesma posio quando possurem o mesmo nmero. A ordem da classificao depende do valor do parmetro da procedure. Raciocnio semelhante aplica-se classificao pela quantidade de ruas cujos dados so arredondados na casa de 102, possibilitando empates, da mesma forma. Este problema poderia ser resolvido de forma alternativa, utilizando coluna de autoincremento com os diferentes valores de habitantes numa tabela auxiliar e esta seria

utilizada para atualizar a tabela base. No entanto, isto dependeria de conhecer o funcionamento do SGBD especfico. Para esta situao que existe o cursor. Vrias outras situaes requerem o mesmo recurso. Trata-se de uma estrutura includa na definio da SQL para permitir, excepcionalmente, o tratamento de registros individuais dentro de um conjunto. Mas lembre-se: A SQL voltada para o tratamento de conjuntos. Somente quando voc no tiver alternativa, ou seja, for obrigado a tratar individualmente, voc utiliza o cursor. Tratase de uma estrutura suportada pelos gerenciadores, com manipulao no padronizada, embora similar. Existem vrias formas de utilizao, mas vamos a um exemplo bsico. Existem diferenas entre os gerenciadores na sintaxe e semntica dos comandos. Voc observar que o tratamento bastante similar ao existente para arquivos em linguagens de programao. Vamos mostrar os passos necessrios para a sua utilizao. Se estiver trabalhando com o utilitrio de linha de comando, necessrio informar a sequncia de caracteres que indica o fim do texto fonte. Por outro lado, se optar pela interface Web que indica o trmino pressinando um boto, no deve ser includa a sequncia.

1. Declarar o cursor. Neste momento voc ainda no sabe quais os dados fazem parte do conjunto que deseja tratar, mas declara como ser realizada a seleo dos dados que sero tratados.
declare nome_do_cursor cursor for select ....... /* /* /* /* /* for update [of...] /* /* /* Pode incluir a clusula de ordenao. */ Existem outras clusula complementares. */ Corresponde a especificar o arquivo */ a ser tratado numa linguagem de */ programao. */ Indica que as linhas do cursor */ sero atualizados*/ default (read only ???) */

Veja que o comando select faz parte integrante do comando da declarao do cursor e ele especifica quais registros sero tratados e, desta forma, ele no opera separadamente.

2. Abertura do cursor. Em algumas implementaes, consegue-se dispensar este passo atravs de tcnicas alternativas. Neste momento, em tese, os dados a serem tratados esto definidos.
open nome_do_cursor /* corresponde ao comando fopen */

3. Declarar variveis auxiliares para armazenamento dos valores obtidos do cursor. Isto dependente de produto utilizado. A sintaxe utilizada abaixo utilizada no Microsoft SQL Server:

declare @v_owner char(15), @v_tabela varchar(50), .....

Em Oracle:
declare v_owner varchar2(40); v_tabela varchar2(40);

4. Leitura dos dados do cursor.


fetch nome_do_cursor into @v_owner,@v_tabela,..... fetch nome_do_cursor into v_owner,v_tabela,.....

Este comando permite a verificao da leitura realizada. Se existe registro a ser processado ou no. No Microsoft SQL Server, @@fetch_status a varivel a ser verificada. No Oracle:
fetch nome_cursor into SSN,nome; exit when nome_cursor%NOTFOUND;

5. As implementaes do SQL possuem comandos de controle de LOOP como


while (condicao) begin .... end

6. Fecha o cursor.
close Nome_do_cursor

7. Liberao da estrutura utilizada. Como estaremos utilizando o cursor dentro de uma procedure, no teremos que nos preocupar com este passo. Alguns produtos fazem isto automaticamente, mesmo fora de uma procedure. 8. Atualizao do registro corrente do cursor. A linha atual pode ser alterada com a clusula
... where current of nome_cursor...

Esta clusula tambm pode ser utilizada para excluir a tupla corrente do cursor com o comando delete. Ela se aplica somente a estes comandos e vlida no escopo do cursor e significa que a alterao afeta somente a linha que foi obtida com o ltimo comando fetch do cursor. Esta clusula no retorna ou seleciona dados e muito menos a posio corrente do cursor. Os dados e a correspondente posio do cursor so obtidos com o comando do fetch.

Desde que no produza efeito colateral, pode-se fazer o update sobre as linhas da tabela base do cursor, utilizando a clusula da forma convencional
... where cdigo = ...

9. A construo bsica seria (incluindo a criao da procedure):


create procedure pr_exemplo (param tipo_param, ...) as Begin declarar variveis declarar cursor abrir o cursor fetch ....... while (condicao_de_termino_do_cursor) begin processa ...... fetch ...... end close Nome end

Vamos utilizar o cursor codificado dentro de uma stored procedure, embora ele possa ser utilizado como script SQL, desvinculado de uma procedure. Mas, precisaramos explicar outros detalhes que no nos interessam neste momento.

10. Nas prximas aulas, faremos a implantao de um projeto fsico de bancos de dados e veremos com mais ateno como so especificadas as diversas formas de restrio. Neste momento, a criao de uma constraint de chave primria feita da seguinte maneira:
alter table tb_cidades2 add constraint ct_cidades_pk primary key(codigo)

Atividade
Siga o seguinte roteiro: 1. Crie a tabela tb_cidades2, conforme abaixo:
tb_cidades2

Coluna codigo nome habitantes qtd_ruas estado classif_hab classif_ruas

Tipo char(15) varchar(50) numeric(20) numeric(20) char(2) int int

Admite valores indefinidos No No No No No Sim Sim

2. Seguindo a notao acima, crie chave primria para a tabela tb_cidades2;

3. Inclua dados na sua tabela, copiando da tabela de nome


tb_cidades_prof2.

4. Crie a procedure de nome


pr_classifica_cidades_por_habitantes

a) A procedure tem um parmetro do tipo caractere que pode receber valores A ou D e afeta o funcionamento da procedure no que se refere ordenao conforme descrito abaixo. Deste modo a assinatura da procedure deve ser exatamente a seguinte:
pr_classifica_cidades_por_habitantes (@ordem char(1))

b) Verifica se valor recebido no parmetro valido, ou seja, A ou D. Se diferente, envia mensagem de erro e encerra a execuo. c) Atravs de um cursor, percorre os registros da tabela, em ordem adequada, e preenche a coluna
classif_hab

com a classificao das cidades por nmero de habitantes, considerando que cidades com a mesma quantidade de habitantes tero a mesma classificao. Repetindo o que foi apresentado, este empate pode ocorrer porque a quantidade de habitantes arredondado em 104. Se o parmetro da procedure for D, a classificao em ordem decrescente, ou seja a primeira cidade a que tem maior quantidade de

habitantes e a ltima colocada tem a menor quantidade de habitantes. A ordem ser contrria se o parmetro for A. Neste update, utilizar o comando convencional, ou seja, sem a clusula current of. Para que isto possa ser realizado, ser necessrio obter o valor da coluna
codigo

que ser importante no comando de atualizao. No coloque a sua procedure em loop infinito. Nos execues repetidas dos testes, no h a necessidade de retornar os valores alterados condio anterior porque, neste exemplo, os novos valores no dependem do valor vigente.

5. Crie a procedure de nome


pr_classifica_cidades_por_ruas

a) A procedure tem um parmetro do tipo caractere que pode receber valores A ou D e afeta o funcionamento da procedure no que se refere ordenao conforme descrito abaixo. Deste modo, a assinatura da procedure deve ser exatamente a seguinte:
pr_classifica_cidades_por_habitantes (@ordem char(1))

b) Verifica se valor recebido no parmetro valido, ou seja, A ou D. Se diferente, envia mensagem de erro e encerra a execuo. c) Atravs de um cursor, percorre os registros da tabela, em ordem adequada, e preenche a coluna
classif_ruas

com a classificao das cidades por quantidade de ruas, levando em conta que a primeira cidade tem a maior quantidade de ruas se o parmetro for D. Se for A, a classificao deve ser em ordem contrria. No coloque a sua procedure em loop infinito.

a) Opcional. Descreva como o problema especfico da classificao das cidades por nmero de habitantes poderia ser resolvido sem a utilizao da estrutura de cursor. Registre a resposta no arquivo de nome seu_registro_academico_cursor.txt. Envie o arquivo ao servidor.

At a prxima aula! Prof. Satoshi Nagayama

Você também pode gostar