Laboratório 4 Base de Dados II 2008/2009 Plano de Trabalho Lab. 4: Programação em Transact-SQL Referências MICROSOFT SQL SERVER - Procedimentos do Lado do Servidor (Stored Procedures) - cont. - Exercícios http://dev.mysql.com/doc 1. Conceito. - Stored Procedures são semelhantes a subrotinas ou subprogramas desenvolvidos noutras linguagens de programação (p.e. C, Pascal, Basic, Java, etc.), mas que são guardados no servidor. - Aceitam parâmetros de entrada e retornam resultados. Isto é, como qualquer subprograma, um procedimento permite a passagem de parâmetros de entrada e de saída, aceitando valores e devolvendo algum tipo de resultado à entidade que o invocou, que pode ser um outro procedimento, um gatilho ou mesmo uma aplicação externa cliente. - Retornam um valor de status indicando se aconteceu um erro, e qual foi. - São basicamente blocos de instruções SQL compiladas num único plano de execução.
EXERCÍCIOS I (base de dados Livro&Livro) Exercício 1. (Exercício 5 da aula prática 3 aqui repetido por conveniência). Crie um procedimento que nos forneça o total de vendas por livro, para uma dada colecção e ano de vendas. Vamos supor que a colecção é a A e que o ano é o 2000. Estratégia. - Vamos começar por por seleccionar na tabela Vendas os registos que correspondem às vendas de livros efectuadas no ano 2000. - Ao mesmo tempo, aproveitamos para fazer a combinação das tabelas Vendas e Vendas- Detalhes através duma operação de junção, mais concretamente uma equijunção. Desta operação, obtemos todos os livros vendidos, assim como a restante informação relacionada com os valores das vendas de livros para o ano pretendido. - De seguida, e agora com base na tabela Livros, seleccionamos todos os livros que pertencem à colecção indicada e continuamos o processo de cálculo, combinando os resultados obtidos nas duas etapas anteriores novamente através duma equijunção. - Por fim, agrupamos a informação obtida por livro, de forma a ser possível calcular o total de vendas por livro, ordenando a lista de livros alfabeticamente. Procedimento que fornece a relação das vendas referentes à colecção A do ano 2000, ordenadas por livro CREATE PROCEDURE VendasLivrosColeccaoAno2000 SELECT VD.Livro, L.Designação, SUM(VD.Total) Total FROM (SELECT D.Livro, V.Total FROM Vendas As V, [Vendas-Detalhes] D WHERE SUBSTRING(CONVERT(nvarchar(22),V.Data,111),1,4)= 2000 VD, (SELECT Código, Designação, Colecção FROM Livros p WHERE Colecção = A ) L WHERE L.Código = VD.Livro GROUP BY VD.Livro, L.Designação ORDER BY VD.Livro C O exemplo anterior mostra, por omissão, como a passagem de parâmetros das linguagens de programação poderiam ser úteis na construção de procedimentos do lado do servidor
(stored procedures). Por exemplo, teríamos todo o interesse em usar o procedimento anterior para uma outra colecção e um outro ano. No entanto, isso não é possível. Parâmetros de Entrada É através de parâmetros de entrada que se passa informação para dentro dum procedimento. Exercício 2. Crie um procedimento que nos forneça o total de vendas por livro, para uma dada colecção e ano de vendas. Isto obriga a reformular o procedimento do exercício anterior de modo a passar-lhe dois parâmetros concretos. O primeiro é referente a uma dada colecção e será armazenado na variável ou parâmetro formal @CódigoColecção. O segundo refere-se a um ano específico e será armazenado na variável ou parâmetro formal @AnoDeVendas. T-SQL 6.7 - Criação do procedimento VendasLivrosPorColeccaoPorAno. Procedimento que nos fornece uma relação das vendas realizadas, por colecção e por ano, agrupando-as por livro. CREATE PROCEDURE VendasLivrosPorColeccaoPorAno (@CódigoColecção VARCHAR(03), @AnoDeVendas VARCHAR(4)) PRINT 'Vendas por Colecção/Ano, Agrupadas por Livro' PRINT 'Colecção: ' + CONVERT(varchar(3), @CódigoColecção) PRINT 'Ano: ' + CONVERT(varchar(4), @AnoDeVendas) PRINT '' SELECT VD.Livro, L.Designação, SUM(VD.Total) Total FROM (SELECT D.Livro, V.Total FROM Vendas V, [Vendas-Detalhes] D WHERE SUBSTRING(CONVERT(nvarchar(22),V.Data,111),1,4)=@AnoDeVendas) VD, (SELECT Código, Designação, Colecção FROM Livros p WHERE Colecção = @CódigoColecção) L WHERE L.Código = VD.Livro GROUP BY VD.Livro, L.Designação ORDER BY VD.Livro C Nota: Podemos definir os valores por omissão dos parâmetros de cada procedimento no SQL Server Management Studio, bastando para tal seleccionar o procedimento e depois os respectivos parâmetros com o rato.
Vejamos um exemplo de execução: USE Livro&Livro EXECUTE VendasLivrosPorColecçãoPorAno a, 2002 Parâmetros de Saída É através de parâmetros de saída que um procedimento devolve ou passa informação para o exterior. Exercício 3. Crie um procedimento que nos forneça alguns dados (número, nome e total) sobre o cliente que, no dia de hoje, efectuou o maior volume de compras na Livro&Livro. T-SQL 6.8 - Criação do procedimento MelhorClienteDeHoje. CREATE PROCEDURE [MelhorClienteDeHoje] @NúmeroCliente INT OUTPUT, @NomeCliente VARCHAR(50) OUTPUT, @TotalCliente MONEY OUTPUT SELECT @NúmeroCliente=C.Número,@NomeCliente=C.Nome,@TotalCliente=sum(V.Total) FROM Vendas as V INNER JOIN Clientes C ON V.Cliente=C.Número WHERE convert(varchar(11),v.data,111)=convert(varchar(11),getdate(),111) GROUP BY C.Número, C.Nome ORDER BY sum(v.total) DESC Após a criação deste procedimento estamos em condições de analisar a sua execução e observar a forma como os parâmetros são utilizados. Para isso, vamos executar: USE Livro&Livro DECLARE @NúmeroCliente INT, @NomeCliente VARCHAR(50), @TotalCliente MONEY EXECUTE MelhorClienteDeHoje @NúmeroCliente OUTPUT, @NomeCliente OUTPUT, @TotalCliente OUTPUT PRINT Melhor cliente de hoje ( + CONVERT(VARCHAR(11),GETDATE(),111) + na loja: PRINT CONVERT(VARCHAR(10),@NúmeroCliente) PRINT @NomeCliente PRINT CONVERT(VARCHAR(25),@TotalCliente)
As variáveis declaradas antes da execução do procedimento não têm que ter o mesmo nome que os parâmetros formais, mas os tipos de dados têm de ser os mesmos, ou serem pelo menos compatíveis. Há uma outra forma de passar informação de dentro para fora dum procedimento. Para isso utiliza-se a instrução RETURN. No entanto, à semelhança da linguagem C, com esta forma de passar informação só se pode passar um dado ou resultado. Exercício 4. Crie um procedimento que nos forneça o número de livros vendidos hoje pela Livro&Livro. T-SQL 6.9 : Procedimento NúmeroLivrosVendidosHoje. CREATE PROCEDURE NúmeroLivrosVendidosHoje DECLARE @NúmeroLivros as SMALLINT SELECT @NúmeroLivros = COUNT(VD.Livro) FROM Vendas VE, [Vendas-Detalhes] VD WHERE VE.Número = VD.Número AND CONVERT(nvarchar(22), VE.Data, 111) = CONVERT(nvarchar(22),getdate(), 111) RETURN @NúmeroLivros Repare-se na declaração da variável @NúmeroLivros imediatamente antes do SELECT, sendo o seu valor devolvido com RETURN após o SELECT. Para se perceber como e onde é que o valor de retorno é guardado, observe-se o seguinte código de execução: USE Livro&Livro DECLARE @NúmeroLivrosVendidos SMALLINT EXECUTE @NúmeroLivrosVendidos = NúmeroLivrosVendidosHoje PRINT Número de livros vendidos hoje: PRINT CONVERT(VARCHAR(5), @NúmeroLivrosVendidos)
Como se pode observar, à semelhança do que acontece em C, do lado exterior ao procedimento há uma variável que, através do operador de atribuição, guarda o valor de retorno do procedimento.