quarta-feira, 16 de janeiro de 2008

Trabalhando com cursores( MSSQL 2000 )

Cursores são utilizados quando precisamos tratar cada linha da consulta de forma indvidual. Para isso utilizamos Cursores, que não é nada mais que um select onde o resultado é retornado linha a linha.

Parece simples não é mesmo?

Bem, aqui vai um roteiro simples de como trabalhar com cursores:

1º declarar cursor

declare Cur_pessoas Cursor
for select Nome, idade from Pessoas

Note que precisamos tbm definir as variaveis de saida

Logo, noso script vai ficar assim:

declare @Nome varchar
declare @Idade numeric

declare Cur_pessoas Cursor
for select Nome, idade from Pessoas

2º Abrir o cursor

Open Cur_Pessoas

Neste momento a consulta já foi feita e está armazenada em cash, agora precisamos recuperar a primeira linha do cursor:

3º Recuperando registros do cursor:

Lembra das duas variáveis que foram criadas? Agora está na hora de utiliza-las, foi criada 1 variável para recuperar cada coluna da consulta, pessoalmente eu acho mais conveniente que criar uma variável do tipo tabela, mas isso fica ao seu critério.

fetch next from Cur_Pessoas into @Nome, @Idade /*A ordem é importante*/

Ok, agora que temos o primeiro registro precisamos fazer um laço e tratar cada registro de forma induvidual.

while (@@fetch_status = 0 ) /*@@Fetch_Status é uma variável do SQL server que indica se um cursor retornou algum registro após o fetch*/
begin

/*Aqui vc faz os tratamentos necessários*/
if exists ( select Nome from Clientes
where nome like '@Nome'
and Idade > @Idade) begin
Update Clientes
Set AlgumField = AlgumaCoisa
where nome like '@Nome'
and Idade > @Idade

/*Não podemos esquecer de pegar o proximo registro*/
fetch next from Cur_Pessoas into @Nome, @Idade

end

end /*While*/

/*Finalizar e desalocar cursor*/

close Cur_Pessoas
deallocate Cur_Pessoas

----------------------------------------------------------------------------------------

Os cursores são muito úteis, mas seu uso deve ser evitado, já que eles consomem mtos recursos da sua máquina. Em outras palavras, use apenas se for estritamente necessário.

Segue um exemplo mais completo ( Retirado de: http://www.linhadecodigo.com.br/Artigo.aspx?id=876 )


create procedure BaixaEstoque( @VenCod Integer) as

--Declarando cursor
DECLARE CurItens --Nome do cursor

CURSOR FOR
SELECT ProdCod, IVQtd FROM Itens WHERE VenCod = @VenCod

--Variáveis utilizadas para o tratamento dos registors
DECLARE @ProdCod INTEGER, @IVQtd MONEY

--Iniciando transação
BEGIN TRANSACTION

--Abrindo cursor
OPEN CurItens

--Atribuindo valores do select nas variáveis
FETCH NEXT FROM CurItens INTO @ProdCod, @IVQtd

--Iniciando laço
WHILE @@FETCH_STATUS = 0

BEGIN

IF (SELECT ProdQtdEst - @IVQtd FROM Produtos WHERE ProdCod = @ProdCod) >= 0

UPDATE Produtos

SET ProdQtdEst = ProdQtdEst - @IVQtd

WHERE ProdCod = @ProdCod

ELSE

BEGIN

--Desfazendo o que foi realizado anteriormente
ROLLBACK TRANSACTION

--Levantando erro

RAISERROR(‘Estoque insuficiente!’, 15, 1)

--Fechando e desalocando cursor aqui também, pois o return sairá do procedimento

CLOSE CurItens

DEALLOCATE CurItens


--Saindo do procedimento

RETURN

END

--Próxima linha do cursor

FETCH NEXT FROM CurItens INTO @ProdCod, @IVQtd
END

--Fechando e desalocando cursor

CLOSE CurItens

DEALLOCATE CurItens

--Caso tudo tenha ocorrido OK, alterando a situação da venda

UPDATE Vendas

SET VenSit = 1

WHERE VenCod = @VenCod

--Confirmando transação
COMMIT TRANSACTION