Desvendando o SQL - Parte IX - Procedimentos Armazenados
Autor: Rubens Lima | Publicado: 2013-08-12T08:48:00-03:00





Galera Anapropéguas, nossa série
de artigos está de volta. Esta já é a nona parte, as anteriores mostraram um
pouco de alguns pontos da linguagem SQL, vimos operadores, funções de
agregação, criação de banco, tabelas e views, também vimos à alteração de
estruturas de tabelas, tipos de campo, consultas, estruturas condicionais e de
repetição, cursores e também conversão de valores. Procurei explanar até agora,
se não tudo, o que achei mais interessante para aqueles que ainda não conheciam
a linguagem SQL. Se por acaso ainda não viram os outros artigos, disponibilizo
os links no final desse artigo.



Hoje vamos falar um pouco sobre
STORED PROCEDURES ou Procedimentos Armazenados, sua utilidade e como usá-lo,
aproveitem bem e boa leitura.



PROCEDIMENTOS ARMAZENADOS


Para os que conhecem programação
PROCEDIMENTOS ARMAZENADOS funcionam semelhantes a procedimentos como em
qualquer linguagem. Para aqueles que não conhecimentos nos permitem:



Colocar parâmetros de entrada e saída;
Conter instruções que podem executar algumas
operações no banco;
Retornar um status de execução;




Com uma STORED PROCEDURE podemos,
por exemplo, retornar o valor de uma consulta de acordo com os parâmetros
passados, chamar outros procedimentos, inserir valores em tabelas de acordo com
determinada situação, dentro outras funcionalidades.



Diretrizes para Procedimentos Armazenados


Alguns pontos devem ser seguidos,
comecemos pela sintaxe de criação, que segue o mesmo padrão dos anteriores
objetos criados no banco, vejamos com criar uma PROCEDURE, lembre que depois de
criada, não é possível criar outra com o mesmo nome, portanto caso precisa
fazer alguma alteração é só trocar o CREATE pelo ALTER.


CREATE { PROC |
PROCEDURE }  

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;lista
de parâmetros&gt; 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @PARAM1 TIPO,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @PARAM2
TIPO

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [
=&nbsp;default ] [ OUT | OUTPUT | [READONLY]



AS

BEGIN

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

END

GO




Nome


Lembre-se de utilizar um nome
funcional para procedure, por padrão vamos utilizar um prefixo “PR” seguido de
nome relativo à funcionalidade da Procedure.



Parâmetros


A lista de parâmetros segue
também determinadas regras a serem seguidas.

Sempre utilize no começo do
parâmetro o caractere ‘@’ seguido do nome escolhido;


Todos os tipos de dados
Transact-SQL podem ser usados como parâmetros (Desvendando
o SQL - Parte II);


Um valor Default por ser usado
para definir o parâmetro, inclusive valor NULL, isso permite que mesmo que o
parâmetro não seja passado à execução da procedure é possível;


OUT ou OUTPUT indica que o
parâmetro é de saída, ou seja, será devolvido ao final da execução da
procedure. Lembrando que parâmetros do tipo text, ntext e image não podem ser
usados com OUTPUT;


Parâmetros marcados como READONLY
não podem ser atualizados ou modificados no corpo do procedimento.&nbsp;Se o
tipo de parâmetro for um tipo com valor de tabela, deverá ser especificado
READONLY;


O BEGIN (Inicio) e END (Fim)
limitam o corpo da procedure, como também as instruções que estiver dentro do
corpo podem ser limitadas pelo BEGIN/END;


Algumas práticas são recomendadas
para a PROCEDURE e para não deixar o artigo muito extenso sugerimos consultar a
página do MSDN.




Limitações


Apesar da extensa gama de instruções
que podem ser utilizadas no corpo da procedure, alguns comandos são restritos e
não podem ser usados. Vejam abaixo:


 

  
CREATE AGGREGATE

  
CREATE SCHEMA

 

  
SET SHOWPLAN_TEXT

  
CREATE DEFAULT

 

  
CREATE ou ALTER TRIGGER

  
SET SHOWPLAN_XML

 

  
CREATE ou ALTER FUNCTION

  
CREATE ou ALTER VIEW

 

  
USE database_name

  
CREATE ou ALTER PROCEDURE

 

  
SET PARSEONLY

  
CREATE RULE

 

  
SET SHOWPLAN_ALL

  


 



Uma PROCEDURE pode fazer
referencia a tabelas não criadas, porque no momento da criação somente a
sintaxe é verificada, somente no momento da execução os objetos referenciados
são resolvidos.




Segurança



Como estamos trabalhando com um
usuário com permissões de banco não veremos a dificuldade na execução da
PROCEDURE, mas com um banco com vários usuários as procedures somente serão
executadas com permissão.


Execução 


Para uma procedure ser executada
colocamos os comandos EXECUTE ou EXEC antes do nome da PROCEDURE:


EXECUTE 
&lt;@Param1, @Param2,...&gt;

GO


-- Or


EXEC 
&lt;@Param1, @Param2,...&gt;

GO




EXEMPLOS


Mostraremos agora alguns exemplos
de criação e execução de procedures, a princípio sem parâmetros e em seguida
vamos incluindo alguns parâmetros e algumas outras opções de acordo com o que
já vimos nos artigos anteriores.


Criando um procedimento simples;


CREATE PROCEDURE PRProduto 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

AS

BEGIN

SELECT CD_REFERENCIA, DESC_PRODUTO, ST_PRODUTO, NR_SERIE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM TBPRODUTO

END

GO



Para executar é só digitar o
comando abaixo:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

EXECUTE PRProduto




Mais de um conjunto de resultados;



CREATE PROCEDURE PRProdutoCategoria

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

AS

BEGIN



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT CD_REFERENCIA, DESC_PRODUTO,
ST_PRODUTO, NR_SERIE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM TBPRODUTO





SELECT P.DESC_PRODUTO, C.DESC_CATEGORIA, S.DESC_SUB

FROM 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBPRODUTO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AS P INNER JOIN 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBSUBCATEGORIA&nbsp;&nbsp;&nbsp; AS S ON S.CD_SUB = P.CD_SUB INNER JOIN 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBCATEGORIA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AS C ON C.CD_CATEGORIA = S.CD_CATEGORIA

WHERE

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C.DESC_CATEGORIA = 'BEBIDAS'



END

GO


Relatório de produtos. Lembra quando fizemos um
cursor que mostrava um relatório com os produtos dos movimentos fechados? Agora
vamos criar uma procedure para executar esse relatório sempre que necessário,
só que agora passando alguns parâmetros.



CREATE PROCEDURE PRRelatProdMovimento (@ST_MOV CHAR(1), @DT_INIMOV DATETIME, @DT_FINMOV DATETIME) 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

AS

BEGIN





&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --O EXEMPLO A
SEGUIR MOSTRA COMO CURSORES PODEM SER ANINHADOS PARA PRODUZIR RELATÓRIOS
COMPLEXOS. O CURSOR INTERNO É DECLARADO PARA CADA PRODUTO.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET NOCOUNT ON;



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DECLARE 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @CD_MOVIMENTO&nbsp;&nbsp;&nbsp;&nbsp; INT,


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @DESC_PRODUTO&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR(50),

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @MENSAGEM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR(200),

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @TP_MOVIMENTO&nbsp;&nbsp;&nbsp;&nbsp; CHAR(1),

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @NR_DOCUMENTO&nbsp;&nbsp;&nbsp;&nbsp; INT,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @QTD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DECIMAL(10,4), 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @UNIDADE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR(5)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT '-------- RELATÓRIO DE PRODUTOS DO MOVIMENTO --------';



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DECLARE
MOV_CURSOR CURSOR FOR




&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT
CD_MOVIMENTO, TP_MOVIMENTO, NR_DOCUMENTO

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM TBMOVIMENTODIARIO

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ST_MOVIMENTO
= @ST_MOV AND

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DTH_MOVIMENTO
BETWEEN @DT_INIMOV AND
@DT_FINMOV

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ORDER BY TP_MOVIMENTO;



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OPEN MOV_CURSOR



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FETCH NEXT FROM MOV_CURSOR 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INTO @CD_MOVIMENTO,
@TP_MOVIMENTO, @NR_DOCUMENTO



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHILE @@FETCH_STATUS
= 0

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BEGIN

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT ' '

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT @MENSAGEM = '----- PRODUTOS DO
MOVIMENTO: ' + 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @NR_DOCUMENTO + ' - ' +

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CASE
@TP_MOVIMENTO --(E - ENTRADA, S - SAIDA, T -
TRANSFERENCIA, D - DEVOLUCAO)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHEN 'E'
THEN 'ENTRADA'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHEN 'S' THEN 'SAÍDA'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHEN 'T' THEN 'TRANSFERÊNCIA'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHEN 'D' THEN 'DEVOLUÇÃO'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT @MENSAGEM



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- DECLARE AN INNER CURSOR BASED&nbsp;&nbsp; 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- ON VENDOR_ID FROM THE OUTER CURSOR.



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DECLARE PROD_CURSOR CURSOR FOR 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT
P.DESC_PRODUTO,
M.QTD_PRODUTO,
U.SGL_UNIDADE

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBMOVIMENTOPRODUTO
M INNER JOIN

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBPRODUTO
P ON P.CD_PRODUTO
= M.CD_PRODUTO INNER JOIN

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBUNIDADE U ON U.CD_UNIDADE = M.CD_UNIDADE

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE
M.CD_MOVIMENTO =
@CD_MOVIMENTO



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OPEN
PROD_CURSOR

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FETCH NEXT
FROM PROD_CURSOR 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INTO @DESC_PRODUTO,
@QTD, @UNIDADE



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IF @@FETCH_STATUS &lt;&gt; 0 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;&gt;'&nbsp;&nbsp;&nbsp;&nbsp; 



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHILE @@FETCH_STATUS
= 0

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BEGIN



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT @MENSAGEM = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ' + @DESC_PRODUTO + ' - ' + CAST(@QTD AS VARCHAR(10)) + '-' + @UNIDADE

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT @MENSAGEM

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FETCH NEXT FROM PROD_CURSOR 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INTO @DESC_PRODUTO,
@QTD, @UNIDADE

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLOSE PROD_CURSOR

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DEALLOCATE PROD_CURSOR

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- GET THE NEXT VENDOR.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FETCH NEXT FROM MOV_CURSOR 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INTO @CD_MOVIMENTO,
@TP_MOVIMENTO, @NR_DOCUMENTO

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLOSE MOV_CURSOR;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DEALLOCATE MOV_CURSOR;



END



Essa é somente uma das muitas
utilidades das Procedures, é bem interessante quando temos processos pesados e
queremos tirar isso de nossa aplicação e jogá-la no servidor. Nem sempre
precisando devolver um resultado, podemos usá-la somente pra executar
procedimentos. 


Tente também fazer outras
procedures com outros processamentos que deseje, e caso tenha alguma dúvida, é
só comentar que terei o prazer de responder. 


No próximo artigo falaremos um
pouco sobre as FUNCTION ou Funções no SQL. Não perca.


Até a próxima.





Artigos anteriores:

Desvendando o SQL - Parte I - Introdução
Desvendando o SQL - Parte II - Criando um Banco de Dados e Tabelas

Desvendando o SQL - Parte III - Alterando Registros


Desvendando o SQL - Parte IV - Consultas


Desvendando o SQL - Parte V - Visões

Desvendando o SQL - Parte VI - Estruturas Condicionais e de Repetição
Desvendando o SQL - Parte VII - Cursores
Desvendando o SQL - Parte VIII - Conversão de Valores