Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
SQL
Professores:
Esp. Eduardo Herbert Ribeiro Bona
Me. Jackson Luis Schirigatti
DIREÇÃO
OBJETIVOS DE APRENDIZAGEM
•• Apresentar e compreender as funções pré-definidas.
•• Apresentar aplicações e exemplos práticos do uso das funções pré-definidas.
•• Apresentar e compreender a lógica condicional nas cláusulas SELECT, WHERE
e ORDER.
•• Conceituar e compreender as funções próprias SQL definidas pelo usuário.
PLANO DE ESTUDO
introdução
6 Pós-Universo
FUNÇÕES
PRÉ-DEFINIDAS
Pós-Universo 7
““
o Oracle inclui muitas funções de SQL construídas diretamente no banco
de dados, que podem ser utilizadas em uma variedade de maneiras em SQL
e PL/SQL. Essas funções podem aceitar qualquer número de parâmetros
e sempre retornam um resultado de um tipo de dado [...] as funções pré-
definidas podem ser funções de uma única linha, funções agregadas, funções
analíticas, funções de referência de objetos ou funções de modelo.
Funções Numéricas
As funções numéricas basicamente recebem e retornam valores numéricos. Da lista
completa e oficial contida nas referências bibliográficas, a Tabela 1 ilustra as funções
numéricas.
select concat(chr(67),
chr(65),chr(67), chr(65))
initcap (texto) Retorna o texto informado com as primeiras letras select initcap(‘eduardo bona’)
de cada palavra convertidas para maiúscula. retorna: Eduardo Bona
lower (texto) Retorna todos os caracteres convertidos em select lower (titulo) from livro
minúsculos. retorna: programação sql i
upper (texto) Retorna todos os caracteres convertidos em select upper (titulo) from livro
maiúsculos. retorna: PROGRAMAÇÃO SQL I
lpad (texto, n, Faz alinhamento à direita e preenche com caracteres select nome, lpad
texto2) à esquerda até uma determinada posição. (sobrenome,15, ‘*’) from livros
O exemplo procura os autores que contenham a where upper (nome) like
palavra “Jackson” e se encontrarem, o sobrenome ‘%jackson%’
sugerido de 15 posições é preenchido com caracteres
à esquerda. retorna
Nome Sobrenome
--------- -----------------
JACKSON ****SCHIRIGATTI
rpad (texto, n, Faz alinhamento à direita e preenche com caracteres select nome, rpad
texto2) à direita até uma determinada posição. (sobrenome,15, ‘*’) from livros
where upper (nome) like
‘%jackson%’
retorna:
Nome Sobrenome
--------- ----------------
JACKSON SCHIRIGATTI****
Pós-Universo 11
CENÁRIOS PRÁTICOS
PARA USO DE FUNÇÕES
PRÉ-DEFINIDAS
Pós-Universo 15
Segundo Price (2009, p. 126), “as funções numéricas são utilizadas para efetuar cálculos.
Essas funções aceitam um número de entrada que pode vir de uma coluna numérica,
ou qualquer expressão que seja avaliada com um número. Então o cálculo é feito e um
número é retornado”. “Já as funções de caractere aceitam entradas de caracteres, que
podem vir de uma coluna em uma tabela, ou de modo geral de qualquer expressão.
Essa entrada é processada e um resultado é retornado” (PRICE, 2009, p. 118). “Com
relação às funções de data/horário, são usadas para obter e processar data/horário”
(PRICE, 2009, p. 170). Veremos nesta parte do estudo os cenários práticos do uso das
funções pré-definidas.
(2) SELECT product_id, price, price - 30, abs(price - 30) FROM products
WHERE products_id < 4
product_id price price - 30 abs(price - 30)
------------- -------------- --------------- ------------------
1 19.95 -10.05 10.5
2 30 0 0
3 25.99 -4.01 4.01;
16 Pós-Universo
Perceba que o uso da função numérica ABS é selecionar os produtos da base de dados/
tabela produtos e apresentar seus preços com o “valor absoluto” (valor absoluto = sem
o sinal negativo). As aplicações deste exemplo e de várias outras funções numéricas,
como vimos na Tabela 1 (truncamento, arredondamento, operações matemáticas e
outras), são utilizadas nas áreas de venda, financeira, embarque e importações, no
uso em tabelas de preços, cálculo de impostos, conversões de moeda, descontos
em preços, peso de produtos em notas fiscais, totais de embarques e estoques, etc.
Uma nota, segundo Price (2009, p. 125), é que “REPLACE( ) não modifica a linha real do
banco de dados; somente a linha retornada pela função é modificada”. Esta e outras
funções da Tabela 2 (alinhamento à esquerda ou à direita, retirada de caracteres,
concatenação, substituição, conversão, supressão de caracteres, etc.) são utilizadas
para a área comercial, produção, logística, marketing, qualidade, tecnologia, financeira
e demais áreas, no uso de apresentações de relatórios, certificados, recibos, mala
direta, importação e exportação de dados, arquivos de dados para envio bancário, e
outros resultados onde são necessárias as manipulações de caracteres.
Datas
Para as aplicações com funções utilizando a manipulação de datas, o exemplo e
resultado (4) apresentam a função EXTRACT, visto na Tabela 3, que mostra nome, ano
e data de nascimento dos clientes de uma empresa com cargo de diretoria.
NOME ANO
------------------------------------------- ----------
JACKSON LUIS SCHIRIGATTI 1970
ANGELA CRISTINA RONCAGLIO SCHIRIGATTI 1972
Vejam que a função EXTRACT extrai o ano da data de nascimento do campo “dt_
nascimento” da tabela “Funcionário”. As aplicações das funções de datas como a
EXTRACT e outras como data corrente, fuso horário, última data de um determinado
mês, número de meses de um período e cálculos com datas são triviais para as mais
diversas áreas e aplicações.
18 Pós-Universo
TO_CHAR(...)
-------------------
19:32:36
LÓGICA CONDICIONAL
20 Pós-Universo
(6)
<?php
$nota = $_GET[“nota”];
if ($nota >= 7) {
echo “Parabéns!”;
} elseif ($nota >= 6) {
echo “Atenção! Melhore sua Nota!”;
} else {
echo “Você corre o risco de reprovação”;
}
Pós-Universo 21
$opcao = $_GET[“op”];
switch($opcao) {
case 1:
echo “Opção 1”;
break;
case 2:
echo “Opção 2”;
break;
default:
echo “Nenhuma Opção”;
}
?>
(7)
select nome, status, case
when status = 1 then ‘Ativo’
else ‘Inativo’
end as status_descricacao
from pessoa
Neste caso será obtido como resposta a este SQL uma tabela com três colunas (nome,
status e status_descricao), sendo a última gerada por meio de uma lógica condicional
CASE WHEN. A utilização da cláusula ELSE é opcional e, deste modo, não é obrigatória;
no caso do não atendimento da expressão contida em WHEN, será retornado NULL
para a coluna em questão.
22 Pós-Universo
(8)
select cod_pedido, valor, frete, case
when valor >= 200 then preco
when valor >= 100 then preco + (frete * 0.5)
else preco + frete
end as valor_total
from pedidos
Com base no mesmo exemplo anterior, que aplicava desconto ao frete com base
no valor da compra, este outro exemplo (9) deixa a cláusula CASE WHEN com uma
extensão maior e basicamente aplica a mesma regra ao valor do frete, no entanto,
para cada uma das validações anteriores aplica um desconto de 20% se o cliente for
VIP. Como se trata de uma regra de três, optamos por fazer a multiplicação do valor
por 0.8 e obter assim o desconto de 20% já no valor descontado, que seria 80% do
valor do pedido.
É comum ver cláusulas CASE WHEN compostas de mais de uma expressão e as
regras de filtros utilizadas em WHERE também podem ser aplicadas aqui com o uso
de AND ou OR e até mesmo com subconsultas e a maioria das expressões SQL.
24 Pós-Universo
(10)
select cod_pedido, valor, frete, case
when (valor >= 200 and cliente.vip = 1) then preco*0.8
when (valor >= 200 and cliente.vip = 0) then preco
when (valor >= 100 and cliente.vip = 1) then (preco*0.8) + (frete * 0.5)
when (valor >= 100 and cliente.vip = 0) then preco + (frete * 0.5)
when (valor < 100 and cliente.vip = 1) then (preco*0.8) + frete
else preco + frete
end as valor_total
from pedido inner join cliente
on (pedido.cod_cliente = cliente.cod_cliente)
where (case
when (valor >= 200 and cliente.vip = 1) then preco*0.8
when (valor >= 200 and cliente.vip = 0) then preco
Pós-Universo 25
when (valor >= 100 and cliente.vip = 1) then (preco*0.8) + (frete * 0.5)
when (valor >= 100 and cliente.vip = 0) then preco + (frete * 0.5)
when (valor < 100 and cliente.vip = 1) then (preco*0.8) + frete
else preco + frete
end) >= 80 and cliente.uf = ‘PR’
atenção
Lembrando que a diferença do uso de CASE WHEN: quando utilizado em
SELECT, obtém respostas customizadas através de uma expressão condicional,
já em uma cláusula WHERE, filtra um resultado obtido também por meio de
uma expressão condicional.
Fonte: os autores.
26 Pós-Universo
(11)
select nome, cpf
from cliente
order by (case
when months_between(current_date, data_nascimento) >= 60*12 then 1
else 2
end) ASC, nome ASC
Pós-Universo 27
Deste modo, a condicional verifica se os meses entre a data atual e a data de nascimento
são superiores ou iguais ao resultado do número 60 (sessenta) multiplicado por 12
(doze), pois como a função months_between retorna o número de meses, é preciso
fazer a conversão em virtude de um ano possuir 18 (dezoito) meses.
É retornado para o atendimento da cláusula o valor 2, e justamente este resultado
é utilizado para a primeira expressão de ordenação, ou seja, as linhas que tiverem o
resultado 1 serão mostradas primeiramente (ordenação ASC), enquanto as demais
com resultado 2 serão exibidas posteriormente.
Como haverá uma repetição de resultados 1 e 2, definimos na consulta o
segundo critério de ordenação como nome (ordenação ASC) e deste modo serão
mostradas neste relatório todas as pessoas que tiverem 60 anos ou mais, ordenadas
alfabeticamente pelo nome, e em seguida as demais pessoas com menos de 60 anos
ordenadas alfabeticamente também.
Tudo isso sem necessidade de duas consultas, UNION ou qualquer outra solução
mais mirabolante. Você poderá também optar pelo uso do próprio CASE WHEN
desenvolvido no SELECT caso demande ordenação por ele. Seria também necessário
o uso dele, uma vez que não se ordena pelo apelido, e sim pela expressão completa.
Separamos para última análise deste assunto o seguinte cenário: uma empresa
tem em um banco de dados uma visão (view) chamada clientes_consumo com os
seguintes campos:
•• cod: inteiro
•• nome_cliente: textual
Este mesmo cliente pediu que você desenvolva um relatório estatístico onde seja
apresentada a quantidade de clientes por estado com os seguintes indicadores:
quantidade de clientes que compraram acima de R$ 200.000,00, quantidade de
clientes que compraram entre R$ 100.000,00 e R$ 200.000,00 e clientes que compraram
abaixo de R$ 100.000,00.
Deste modo, o resultado seria algo próximo deste layout:
Cada desenvolvedor pensaria numa solução pra isso. Este questionamento já foi feito
algumas vezes para diversos alunos e desenvolvedores da equipe e várias respostas
foram obtidas, dentre elas:
•• Fazer três consultas para cada cenário com group by e depois juntar na
aplicação;
•• Criar três views, uma para cada cenário, e depois juntar em uma consulta só;
Mas a mesma solução que imaginamos, depois de muita prática, e que somente
alguns bons desenvolvedores SQL concordaram que era a melhor, usaria apenas
uma consulta e lógica condicional.
Antes disso, vamos realizar a consulta com subconsultas e adotar a solução mais
escolhida pelos desenvolvedores (exemplo 12):
(12)
select
distinct consumo.estado_sigla,
(select count(*) from clientes_consumo as cliente_consumo2 where estado_
sigla = consumo.estado_sigla and movimento_3m <= 100000) as ate_100,
(select count(*) from clientes_consumo as cliente_consumo2 where estado_
sigla = consumo.estado_sigla and movimento_3m BETWEEN 100000 AND 200000)
as entre_100_200,
(select count(*) from clientes_consumo as cliente_consumo2 where estado_
sigla = consumo.estado_sigla and movimento_3m >= 200000) as acima_200
from clientes_consumo as consumo
order by estado_sigla
Agora, com CASE WHEN é possível fazer coisas mágicas. Veja a consulta com o
mesmo resultado sem subconsultas, como ficaria (exemplo 13):
(13)
select
estado_sigla,
sum(case when movimento_3m <= 100000 then 1 else 0 end) as ate_100,
sum(case when movimento_3m BETWEEN 100000 AND 200000 then 1 else 0
end) as entre_100_200,
sum(case when movimento_3m >= 200000 then 1 else 0 end) as acima_200
from clientes_consumo
group by estado_sigla
order by estado_sigla
Com o uso da condicional lógica CASE WHEN, fizemos o uso da função de agregado
SUM para retornar a soma dos resultados, que de acordo com a condicional, resultam
em 1 ou 2. Não utilizamos COUNT, pois a função COUNT faz a ocorrência de linhas
e aí não teríamos como fazer 3 validações na mesma consulta, mas com o uso de
SUM, sendo os resultados 1 ou 2, seria possível obter um resultado igual, com uma
consulta muito menor em sintaxe e em consultas internas.
Logicamente, este é um uso bem complexo, mas entre um relatório e outro,
principalmente os estatísticos, seu poder de criatividade para buscar soluções pelos
menores caminhos possíveis deverá ser posto em prática. Por isso, não se esqueça
do CASE WHEN.
saiba mais
CASE pode ser usada em qualquer instrução ou cláusula que permita uma
expressão válida. Por exemplo, você pode usar CASE em instruções, como
SELECT, UPDATE, DELETE e SET, e em cláusulas como select_list, IN, WHERE,
ORDER BY e HAVING.
FUNÇÕES PRÓPRIAS
EM SQL
32 Pós-Universo
Funções Próprias
Para Ramalho (2005, p. 8-9),
““
uma função é uma sub-rotina parecida com uma stored procedure. O SQL
Server 2005 permite que o usuário crie suas próprias funções, além de usar
aquelas que já fazem parte da linguagem Transact-SQL. Uma função definida
pelo usuário é criada pelo comando CREATE FUNCTION.
Por sua vez, segundo Silberschatz, Korth e Surdarshan (2006, p. 95), “a partir da versão
SQL:1999, a SQL permite a definição de funções, procedimentos e métodos. Esses
podem ser definidos pelo componente procedural da SQL:1999 ou por uma linguagem
de programação externa, como Java, C ou C++”.
As funções criadas pelos usuários também são chamadas de User-Defined Functions
(UDF), ou seja, funções definidas pelo usuário. Silberschatz, Korth e Surdarshan (2006)
apresentam o exemplo 14 da criação de uma função, onde dado o nome de um
cliente, retorna a contagem do número de contas pertencentes a esse cliente em
forma de tabelas. Esse tipo de funções são chamadas “funções de tabelas”. “A função
do exemplo retorna uma tabela contendo todas as contas que uma determinada
pessoa possui. Observe que o parâmetro de função é referenciado prefixando-o com
o nome da função (conta_de.nome_cliente)” (SILBERSCHATZ; KORTH; SURDARSHAN,
2006, p. 95).
(14)
create function contas_de (nome_cliente char (20))
return table (
numero_conta char (10),
nome_agencia char (15),
saldo numeric(12,2))
return table
( select numero_conta, nome_agencia, saldo from conta
where exist (select * from depositante);
Pós-Universo 33
(15)
SELECT *
FROM table (contas_de (‘schirigatti’))
Em geral, contudo, as funções com valor de tabela podem ser imaginadas como views
parametrizadas que generalizam a noção comum de views permitindo parâmetros
(SILBERSCHATZ; KORTH; SURDARSHAN, 2006, p. 95).
Um outro exemplo de função (exemplo 16), segundo PRICE (2009), ilustra no
Oracle 11g a criação de uma função chamada “average_produc_price ()”, a qual
retorna o preço médio dos produtos cujo valor de “product_type_id” é igual ao valor
do parâmetro de entrada. O parâmetro product_type_id é o código do produto da
tabela produtos. AVG(price) calcula a média dos processos dos produtos pesquisados
como resultado inseridos em v_average_product_price, que é retornado pela função
através de RETURN. Percebam que a busca (seleção), o cálculo da média dos preços e
a condição de busca na tabela produtos são realizados entre a estrutura BEGIN/END.
(16)
CREATE FUNCTION average_produc_price (p_product_type_id) (
p_product_type_id IN INTEGER) RETURN NUMBER AS
v_average_product_price NUMBER;
BEGIN
SELECT AVG(price)
INTO v_average_product_price
FROM products
WHERE product_type_id = p_product_type_id;
RETURN v_average_product_price;
END average_produc_price;
34 Pós-Universo
(17)
SELECT average_produc_price(1) FROM dual;
average_produc_price(1)
--------------------------------
29.965
saiba mais
As procedures e funções têm vantagens em um ambiente de banco de
dados. As procedures são compiladas e armazenadas no dicionário de
dados de uma vez; quando mais de um usuário precisar chamá-la, ela já
estará compilada e haverá somente uma cópia da procedure armazenada
no shared pool. Uma procedure diferente da função não retorna um valor,
apenas um código de status. Entretanto, as procedures podem ter uma ou
mais variáveis que podem ser definidas e retornadas como parte de sua
lista de argumentos.
3. Uma facilidade que pode ser obtida com a lógica condicional CASE WHEN é a de
praticamente poder utilizá-la em qualquer momento da consulta SQL, inclusive na
cláusula ORDER. Marque a alternativa correta, que justifica o uso da condicional CASE
WHEN na cláusula ORDER:
a) current_timestamp.
b) extract.
c) dbtimezone.
d) months_between.
resumo
Podemos resumir o nosso estudo nos conceitos e nas aplicações das funções pré-definidas,
aplicações das funções em cenários práticos, uso da lógica condicional CASE WHEN e na criação de
funções pré-definidas pelo usuário. Com relação às funções pré-definidas, as principais apresentadas
em nosso estudo são as funções numéricas e as de manipulação e conversão de caracteres e
datas. Vimos que o uso das funções pré-definidas funcionam de forma muito parecida a dos
operadores que manipulam itens de dados e retornam um valor. Assim como também em uma
linguagem de programação normal, funções recebem dados passados mediante parâmetros,
que podem ser caracterizados por um ou mais argumentos e resultam em um retorno único.
Também compreendemos que as funções, tanto as pré-definidas como as definidas pelos usuários,
possuem uma importância dentro da linguagem SQL quanto ao reuso dos cálculos prontos,
facilitando a programação e reutilização dos códigos. Os cenários práticos apresentados em nosso
estudo são os mais variados, onde houver uma aplicação em uma empresa ou setor comercial,
financeiro ou produtivo, ou outro qualquer que necessite de operações de cálculos, manipulação
de caracteres e datas, as funções podem ser utilizadas para facilitar o desenvolvimento do código
SQL. Quanto à aplicação da lógica condicional, como a cláusula CASE WHEN, vimos que ela traz
grandes benefícios de organização e visualização, deixando assim mais próximo o código em
uma estrutura condicional comum, sendo que praticamente é possível utilizá-la em qualquer
momento da consulta SQL. Contudo, entendemos que a CASE WHEN é mais utilizada na cláusula
SELECT para condicionar a seleção, na WHERE para condicionar os resultados da filtragem e na
cláusula ORDER para condicionar as classificações. E, por fim, compreendemos a importância
do estudo das funções definidas pelos usuários, onde é possível criar funções de um retorno
(numérico, caractere ou outro tipo de dado), bem como o retorno de tabelas de dados, através
das chamadas “funções de tabelas”.
material complementar
Na Web
Acesse o link da documentação do SQL da Microsoft (Transact-SQL) para conhecer mais
sobre as dezenas de funções de banco de dados, como agregação, analíticas, agrupamento,
configuração, conversão, matemático, lógica, data e hora, etc.:
Web: <https://docs.microsoft.com/pt-br/sql/t-sql/functions/string-functions-transact-sql>.
Na Web
Acesse o link da documentação do SQL da Microsoft (Transact-SQL) para conhecer mais sobre
as funções pré-definidas de cadeia de caracteres:
Web: <https://docs.microsoft.com/pt-br/sql/t-sql/functions/string-functions-transact-sql>.
referências
BRYLA, B.; LONEY, K. Oracle Database 11g - Manual do DBA: administre um banco de dados
corporativo Oracle escalável e seguro. Porto Alegre: Bookman, 2009.
FREEMAN, R. Oracle, referência para o DBA: técnicas essenciais para o dia-a-dia do DBA. Rio de
Janeiro: Elsevier, 2005.
GONÇALVES, E. PL/SQL: domine a linguagem do banco de dados SQL. São Paulo: Casa do Código,
2015.
PRICE, J. Oracle Database 11g: domine SQL e PL/SQL no banco de dados Oracle. Porto Alegre:
Bookman, 2009.
RAMALHO, J. A. A. Microsoft SQL 2005: guia prático. Rio de Janeiro: Elsevier, 2005.
SILBERSCHATZ, A.; KORTH, H. F.; SURDARSHAN, S. Sistemas de Banco de Dados. Rio de Janeiro:
Elsevier, 2006.
resolução de exercícios
4. b) extract.