SQL – Cursores
Olá pessoal.
Vamos falar hoje sobre “Cursores” em SQL, mas vamos falar de forma simples e prática, sem enrolação.
“Cursores” são mais ou menos como sub-consultas retornadas em uma estrutura parecida com tabela, para uso de funções e procedures.
Como assim? Normalmente o select no retorna dados filtrados de tabelas, simples assim.
O “Cursor” nos retorna estes mesmo dados, mas de forma que consigamos aplicá-los em funções e procedures.
Vamos supor que eu tenha 3 tabelas, uma chamada “Usuarios”, outra chamada “Enderecos” e outra chamada “Completo”, como segue logo abaixo:
Usuarios: Nome Idade Sexo Juca Pimenta 33 M Joao Silverio 25 M Bruna Beleza 18 F Enderecos: Nome Rua Numero Bairro Juca Pimenta Rua Feliz 115 Alegria Joao Silverio Av do Balão 25 Centro Bruna Beleza Tv Bambú 70 Jardim da Lagoa Completo: Nome Idade Sexo Endereco
Eu deixei a tabela “Completo” vazia de propósito para explicar o “Cursor”.
Neste caso, vamos filtrar as tabelas “Usuarios” e “Enderecos” e juntar tudo na tabela “Completo”.
Mas primeiro, vamos criar uma procedure para isso:
CREATE PROCEDURE procJuntaTudo(@pNome AS VARCHAR(20), @pIdade AS INT, @pSexo AS VARCHAR(1), @pRua AS VARCHAR(20), @pNumero AS INT, @pBairro ASVARCHAR(20)) AS BEGIN INSERT INTO Completo (Nome, Idade, Sexo, Endereco) VALUES(@pNome, @pIdade, @pSexo, @pRua + ', ' + @pNumero + ', ' + @pBairro) END
Nessa função, repare que passo todos os campos das duas tabelas como parâmetros da função e depois gravo todos dados em somente uma.
Mas não podemos usar essa função dentro de um “Select”, ai entra a necessidade do “Cursor”.
No “Cursor” vamos montar o “Select” que filtrará os dados, e os deixará prontos para serem usados na função.
Vamos definir o “Cursor”:
DECLARE cursorJuntaTudo CURSOR LOCAL FORWARD_ONLY READ_ONLY FOR SELECT US.Nome, US.Idade, US.Sexo, END.Rua, END.Numero, END.Bairro FROM Usuarios US LEFT JOIN Enderecos END ON (END.Nome = US.Nome)
Vejam, nós declaramos um “Cursor” chamado “cursorJuntaTudo” e dentro dele fizemos um “Select” da tabela “Usuarios” com left join da tabela “Enderecos”.
O “Cursor” vai disponibilizar estes dados como se fossem uma tabela, e utilizaremos como segue:
DECLARE @Nome AS VARCHAR(20) DECLARE @Idade AS INT DECLARE @Sexo AS VARCHAR(1) DECLARE @Rua AS VARCHAR(20) DECLARE @Numero AS INT DECLARE @Bairro AS VARCHAR(20) DECLARE cursorJuntaTudo CURSOR LOCAL FORWARD_ONLY READ_ONLY FOR SELECT US.Nome, US.Idade, US.Sexo, END.Rua, END.Numero, END.Bairro FROM Usuarios US LEFT JOIN Enderecos END ON (END.Nome = US.Nome) OPEN cursorJuntaTudo FETCH NEXT FROM cursorJuntaTudo INTO @Nome, @Idade, @Sexo, @Rua, @Numero, @Bairro WHILE @@FETCH_STATUS = 0 BEGIN EXEC procJuntaTudo @Nome, @Idade, @Sexo, @Rua, @Numero, @Bairro FETCH NEXT FROM cursorJuntaTudo INTO @Nome, @Idade, @Sexo, @Rua, @Numero, @Bairro END CLOSE cursorJuntaTudo DEALLOCATE cursorJuntaTudo
Logo após a declaração do “Cursor”, nós o abrimos com o comando “OPEN”.
Agora preste atenção no comando “FETCH NEXT”, ele indica para usar o próximo registro do “Cursor”, então logo após o “OPEN”, usamos o “FETCH” para apontar o “Cursor” para o primeiro registro dispovível.
O “FETCH” vai pegar a próxima linha do “Cursor” e jogar os dados para dentro das variáveis @Nome, @Idade, @Sexo, @Rua, @Numero, @Bairro. Estas variáveis, tem que ser na mesma quantidade e tipo do “Select” declarado dentro do “Cursor”.
Depois fazemos um “WHILE” enquanto o “@@FETCH_STATUS” seja igual a 0, o que significa que o “WHILE” vai executar enquanto houver dados, quando terminarem todos os registros o “@@FETCH_STATUS” fica -1 e o laço termina.
Dentro do “WHILE” executamos a função que junta todos dados na tabela “Completo”, passando como parâmetro as variáveis do “FETCH”.
No final do “WHILE”, usamos o “FETCH” novamente para pulara para o próximo registro do “Cursor”, e é nesse momento, quando não houver mais registros que o “@@FETCH_STATUS” vai mudar para -1.
Por fim, fechamos o “Cursor” com o comando “CLOSE” e liberamos a memória ocupada por ele com o comando “DEALLOCATE”.
Dessa forma nossa tabela “Completo” ficará assim:
Completo: Nome Idade Sexo Endereco Juca Pimenta 33 M Rua Feliz, 115, Alegria Joao Silverio 25 M Av do Balão, 25, Centro Bruna Beleza 18 F Tv Bambú, 70, Jardim da Lagoa
Dúvidas pessoal, é só escrever aqui nos comentários.
Abraço.