Apostila PostgreSQL
Apostila PostgreSQL
Apostila PostgreSQL
MÓDULO 02
MÓDULO 03
MÓDULO 04
MÓDULO 05
MÓDULO 06
MÓDULO 07
003
MÓDULO 1
INTRODUÇÃO E INSTALAÇÃO
004
MÓDULO 1
Introdução: O que é um Banco de Dados? 005
Um banco de dados é um conjunto de dados organizados dentro de uma ou mais tabelas, que terão alguma relação entre
si.
Partimos de uma informação isolada, na sua forma mais simples, e a partir de um conjunto de diversas informações
isoladas, conseguimos organizar essas informações para criar tabelas e bancos de dados.
Introdução: O que é um Banco de Dados? 006
Agora que já sabemos o que é o SQL, surge a seguinte dúvida: o que é um Sistema de Gerenciamento de Banco de
Dados, ou SGBD?
Um SGBD permite ao desenvolvedor trabalhar com diferentes tabelas de um banco de dados através de uma interface.
Essa interface seria basicamente um programa que nos permite fazer a leitura de tabelas de um banco de dados e
utilizar o SQL para manipular esses dados, tudo de uma maneira bem visual e user-friendly.
Existem alguns SGBDs para Bancos de Dados Relacionais que são muito utilizados por grandes empresas. Abaixo,
temos os 4 principais programas para SGBDs.
É importante que fique claro que todos esses SGBDs utilizam o SQL como linguagem de programação.
Agora vamos instalar o programa pelo qual conseguiremos interagir com o nosso banco de dados.
O SGBD, conforme explicado anteriormente, será composto por um servidor e uma interface.
Para o caso do PostgreSQL, teremos que instalar o PostgreSQL Server e o pgAdmin 4, respectivamente.
SERVIDOR INTERFACE
Instalação do PostgreSQL 010
Na página inicial, selecione o sistema operacional do seu computador. Utilizaremos o Windows como exemplo:
Instalação do PostgreSQL 011
Selecione a versão suportada pelo seu sistema operacional. No nosso exemplo, instalaremos a versão mais atual
suportada pelo Windows 64 bits:
Instalação do PostgreSQL 013
Finalizado o download,
clique sobre o executável
para iniciarmos a
instalação.
Instalação do PostgreSQL 014
Após isso, clicamos em Servers e selecionamos o servidor que queremos acessar. Solicitada novamente a senha, a
digitamos mais uma vez e clicamos em OK:
Abrindo o PostgreSQL / pgAdmin 4 025
Clique em northwind.sql:
Criando as tabelas do BD Northwind 031
1
Criando as tabelas do BD Northwind 034
MÓDULO 2
MÓDULO 2
SELECT FROM - Selecionando dados das tabelas 040
Com ele, podemos retornar todas as colunas de uma tabela, somente uma ou algumas delas.
1
SELECIONANDO TODAS AS COLUNAS DA TABELA:
Com ele, podemos retornar todas as colunas de uma tabela, somente uma ou algumas delas.
2
SELECIONANDO APENAS UMA COLUNA DA TABELA:
Com ele, podemos retornar todas as colunas de uma tabela, somente uma ou algumas delas.
3
SELECIONANDO MAIS DE UMA COLUNA DA TABELA:
Colunas de uma tabela podem ser renomeadas por meio do comando AS. Se o nome for um texto único, o nome da nova
coluna pode ser escrito com ou sem as aspas duplas.
Caso precise renomear com um nome composto, utilize as aspas duplas, porém nomes compostos não são considerados
uma boa prática.
Também utilize as aspas duplas caso queira preservar as letras maiúsculas do seu alias, pois, sem elas, o SQL considera
todas as letras como minúsculas, independentemente da forma como você digitou no seu código. Veja:
Isso será importante quando precisarmos, mais para frente em nossos estudos, informar junto ao nome da coluna à
qual tabela ela pertence. Assim, não precisaremos repetir todo o nome da tabela à esquerda dos nomes das colunas,
somente seu alias:
O comando LIMIT permite que selecionemos apenas as N primeiras linhas de uma tabela.
É ótimo para fazer o reconhecimento de uma tabela, principalmente se esta for muito extensa, com muitos registros
(linhas).
Por exemplo: a tabela orders do BD Northwind possui 830 registros. Vamos supor que queremos retornar apenas as
100 primeiras dentre essas linhas. Para isso, utilizamos o LIMIT ao final do nosso SELECT, desta forma:
SELECT DISTINCT – Selecionando valores distintos 047
MÓDULO 3
FILTROS
050
MÓDULO 3
WHERE – Filtros com textos 051
O comando WHERE nos permite criar filtros nas tabelas dos bancos de dados, seja com colunas de texto, números ou
datas.
Vejamos um exemplo de como utilizar este comando com uma coluna de texto.
Na tabela customers do BD Northwind, temos clientes cadastrados de vários países ao redor do mundo. Vamos supor
que a gente queira filtrar somente os clientes da França.
Dessa forma, teremos no nosso resultado somente os clientes que tenham os campos da coluna country preenchidos
com ‘France’:
WHERE – Filtros com textos 053
Portanto, ‘france’ não é o mesmo que ‘France’. Cada caractere deve ser filtrado exatamente conforme está registrado
na tabela: se alguma letra for maiúscula, como neste caso, utilize-a desta forma, caso contrário, não serão retornados os
resultados corretamente. Veja só:
Como o filtro foi informado somente com letras minúsculas (france), mas na tabela estava registrado com a primeira
letra maiúscula (France), não foram retornados valores.
WHERE – Filtros com números 054
Vamos imaginar que a gente precise saber quais produtos estão com o estoque zerado para poder comunicar ao setor
de compras sobre a necessidade de fazer a reposição desses produtos.
Assim, teremos no nosso resultado somente os produtos que estejam com o estoque (units_in_stock) igual a zero:
WHERE – Filtros com números 056
Com dados numéricos, podemos utilizar qualquer operador lógico em nossos filtros:
= (igual) < (menor) > (maior) <= (menor ou igual) >= (maior ou igual) <> (diferente)
Veja só:
Podemos, por exemplo, filtrar somente os produtos cujo valor unitário (unit_price) seja maior ou igual a 50:
WHERE – Filtros com datas 057
Também podemos filtrar datas. Nesses filtros, também podemos utilizar qualquer operador lógico:
= (igual) < (menor) > (maior) <= (menor ou igual) >= (maior ou igual) <> (diferente)
Devemos sempre informar a data que queremos utilizar como parâmetro do nosso filtro entre aspas simples, no padrão
‘aaaa-mm-dd’.
Por exemplo: Vamos supor que, agora, precisamos saber quais foram os pedidos (orders) efetuados a partir de
01/01/1998.
Dessa forma, obteremos o seguinte resultado, somente com os pedidos efetuados a partir da data informada ao
comando WHERE:
WHERE – Operadores AND e OR 059
Os operadores AND e OR são usados para filtrar linhas da tabela baseado em mais de uma condição.
• O OR mostra as linhas da tabela se pelo menos uma das condições for atendida.
WHERE – Operadores AND e OR 060
Imaginemos que queiramos selecionar somente os clientes cuja profissão seja 'Owner’, e o país de origem seja 'France’.
Perceba que temos duas condições que precisarão ser atendidas nesta consulta:
A coluna contact_title precisa conter a informação ‘Owner’, assim como a coluna country também precisa conter a
informação ‘France’. Se uma dessas condições não for preenchida, ou seja, se o cliente for ‘Owner’, mas não morar no
país ‘France’, ou se ele morar no país ‘France’, mas não for ‘Owner’, esse cliente não deve aparecer no resultado.
Somente deverá aparecer se ele for ‘Owner’ E morar no país ‘France’.
Repare que, no resultado, foram retornados somente os clientes que preencheram ambas as condições:
WHERE – Operadores AND e OR 062
E quando queremos que apareça no resultado todos os registros que atendam pelo menos um dos critérios?
Imagine que agora, precisamos saber quais são todos os clientes que morem no México ou na França.
Assim, teremos todos os clientes que atenderam ao menos uma das condições:
WHERE e LIKE – Filtros especiais com textos 064
O LIKE é usado em conjunto com o WHERE para procurar por um determinado padrão em uma coluna.
Imagine que a gente queira saber quais produtos são medidos em caixas (boxes).
Se pegarmos uma amostra da nossa tabela products, veremos que não existe uma coluna cujos campos estejam
preenchidos somente com o termo ‘boxes’. O que temos é a coluna quantity_per_unit que, dentre as medidas, contém a
palavra boxes em alguns de seus registros. Veja:
WHERE e LIKE – Filtros especiais com textos 066
Portanto, para informar um parâmetro ao operador LIKE, devemos utilizar a sinal de % quando sabemos que o termo
que queremos pesquisar está entre outras informações em determinados campos de uma coluna:
Assim, o LIKE entende que, independentemente de quantos caracteres existam antes ou depois do termo ‘boxes’, os
registros que contenham este termo devem ser retornados:
WHERE e LIKE – Filtros especiais com textos 068
Se nós soubermos exatamente quantos caracteres existem antes ou depois de determinado termo que queremos
procurar, podemos utilizar o caractere especial _ em vez de %. Repare nos campos abaixo em destaque:
Antes do termo ‘boxes’, podemos perceber que existem exatamente três caracteres: dois para os valores (36 ou 12) e
mais um para o espaço. Assim, se quisermos retornar, por exemplo, somente esses dois campos, em vez de utilizar o %,
podemos utilizar três underlines ( ___ ), um para cada caractere que vem antes do termo boxes.
WHERE e LIKE – Filtros especiais com textos 069
Desta forma:
Veja o resultado:
WHERE e IN – Uma alternativa aos múltiplos ORs 070
O operador IN permite que sejam especificados múltiplos critérios dentro do WHERE. O IN é uma alternativa ao uso de
múltiplos operadores OR para filtrar dados de uma mesma coluna.
Vejamos um exemplo: vamos supor que precisemos retornar todos os clientes que morem no México, no UK ou no
Canadá. Com o que já aprendemos até aqui, poderíamos resolver essa questão utilizando múltiplos ORs:
WHERE e IN – Uma alternativa aos múltiplos ORs 071
Porém, temos uma maneira mais “elegante” de se retornar o mesmo resultado, fazendo uso do operador IN.
Veja só:
WHERE e BETWEEN – Filtrando intervalos 072
Se temos uma alternativa mais elegante para múltiplos ORs, que é o operador IN, também a temos para o AND quando
precisamos filtrar dados de uma mesma coluna que armazene números ou datas.
Suponhamos que a gente queira saber quais produtos possuem um unit_price entre 50 e 100.
Portanto, para sintetizar este código, podemos utilizar o operador BETWEEN. Assim, não precisamos repetir o nome da
mesma coluna:
WHERE e BETWEEN – Filtrando intervalos 074
O exemplo anterior foi com uma coluna de números, vejamos agora como também é possível utilizar o BETWEEN com
datas.
Imagine que precisamos filtrar todos os pedidos efetuados entre 01/01/1997 e 31/12/1997.
Novamente, podemos utilizar o AND, mas para isso, precisamos repetir o nome da coluna utilizada (order_date):
WHERE e BETWEEN – Filtrando intervalos 075
Podemos obter este mesmo resultado com o operador BETWEEN, assim não precisamos repetir o nome da coluna
order_date:
Detalhe: o operador BETWEEN é inclusivo, ou seja, os valores passados a ele são incluídos no resultado.
Portanto, se você não deseja incluir os valores no resultado (somente o que estiver entre tais valores), então
o BETWEEN pode não ser a melhor solução.
076
MÓDULO 4
AGRUPAMENTOS
AGRUPAMENTOS
077
MÓDULO 4
COUNT 078
SELECT
COUNT(coluna)
FROM tabela;
Pois…
Sintaxe:
SELECT
SUM(coluna)
FROM tabela;
As funções de agregação AVG, MIN, MAX retornam, respectivamente: a média, o menor e o maior valor de uma
coluna.
Sintaxe:
O GROUP BY é usado junto com funções de agregação (COUNT(), MAX(), MIN(), SUM(), AVG()) para agrupar valores
de acordo com uma ou mais colunas.
Abaixo, vemos um exemplo do comando GROUP BY aplicado em conjunto com a função de agregação SUM para
retornar a soma total de estoque (units_in_stock) por supplier_id.
GROUP BY – Criando agrupamentos 085
Veja agora como agrupamos a quantidade total de clientes por país, ordenando esse
agrupamento pela contagem em ordem crescente:
GROUP BY, WHERE e HAVING – Filtros em agrupamentos 086
A combinação GROUP BY + WHERE nos permite criar filtros antes de agrupar uma
tabela, para depois fazer o agrupamento de dados a partir de uma ou mais colunas
dessa tabela.
Vamos a um exemplo:
Neste caso, primeiro a gente vai precisar filtrar a tabela customers para retornar
apenas os clientes que tenham o contact_title = ‘Owner’. Para isso, usamos o
WHERE.
Assim, podemos fazer uma contagem (COUNT(*)) apenas dos registros retornados
(os clientes cujo contact_title seja igual a “Owner”), agrupando-os (GROUP BY) pelo
país (country).
Já a combinação GROUP BY + HAVING nos permite primeiro fazer o agrupamento de dados a partir de uma ou mais
colunas de uma tabela, para depois criar filtros a partir desse agrupamento.
Vamos a um exemplo:
Portanto, para saber quando utilizar o GROUP BY associado à cláusula WHERE ou à cláusula HAVING, você deve se
perguntar:
Este filtro precisa ser feito na tabela que já existe ou no agrupamento que estou criando?.
SE SUA
NA TABELA: NO AGRUPAMENTO:
RESPOSTA FOR:
UTILIZE O WHERE UTILIZE O HAVING
ANTES DO GROUP BY DEPOIS DO GROUP BY
089
MÓDULO 5
JOINS
090
MÓDULO 5
Introdução 091
Os JOINs no SQL têm como objetivo relacionar as diferentes tabelas dos nossos bancos de dados.
Com eles, conseguimos dar um passo além nas nossas análises, permitindo cruzar informações de diferentes tabelas.
Para criar JOINs, o primeiro passo é descobrir qual coluna as tabelas que queremos relacionar têm em comum.
Será através dessa coluna que o SQL saberá a forma como ele deve cruzar os dados.
Exemplo: as tabelas "products" e "order_details" possuem uma coluna em comum, chamada "product_id".
É daí que vêm os conceitos de CHAVE PRIMÁRIA e CHAVE ESTRANGEIRA, que veremos a seguir.
Chave Primária vs. Chave Estrangeira 092
Uma Chave Primária é uma coluna que identifica as informações distintas em uma tabela. Geralmente é uma coluna de
ID. Toda tabela terá uma, e somente uma, chave primária. Essa chave é utilizada como identificador único da tabela,
sendo representada por uma coluna que não receberá valores repetidos.
Já uma Chave Estrangeira é uma coluna que permite relacionar as linhas de uma segunda tabela com a Chave Primária
de uma primeira tabela.
Ao lado, vemos que a tabela products possui uma TABELA PRODUCTS TABELA ORDER_DETAILS
coluna chamada product_id, com valores que não se
repetem. Essa será a Chave Primária.
Uma Tabela Dimensão é uma tabela que contém características de um determinado elemento: lojas, produtos,
funcionários, clientes, etc.
Nessa tabela, nenhum dos elementos principais irá se repetir. É onde vamos encontrar nossas chaves primárias.
Já uma Tabela Fato é aquela que vai registrar os fatos ou acontecimentos de uma empresa/negócio em determinados
períodos de tempo (vendas, devoluções, aberturas de chamados, receitas, despesas, etc).
Geralmente, é uma tabela com milhares de informações, composta essencialmente por colunas de ID, conhecidas
como chaves estrangeiras, usadas para buscar as informações complementares de uma tabela dimensão.
No exemplo da página anterior, a tabela products é a tabela Dimensão e a order_details é a tabela Fato.
Tabela Dimensão vs. Tabela Fato 094
A sintaxe mais simples para relacionar 2 tabelas (que tenham a 'Coluna1' em comum é a seguinte):
SELECT
*
FROM
Tabela_A
(xxxx) JOIN Tabela_B
ON Tabela_A.Coluna1 = Tabela_B.Coluna1;
Com a opção acima, trazemos em uma mesma consulta TODAS as colunas das duas tabelas relacionadas, isso porque
usamos o *.
Sintaxe 096
Caso a gente queira escolher colunas específicas para visualizar na consulta final, seguimos a seguinte estrutura:
SELECT SELECT
Tabela_A.Coluna1, ta.Coluna1,
Tabela_A.Coluna2, ta.Coluna2,
Tabela_A.Coluna3, ta.Coluna3,
Tabela_B.Coluna4 tb.Coluna4
FROM FROM
Tabela_A Tabela_A ta
(xxxx) JOIN Tabela_B (xxxx) JOIN Tabela_B tb
ON Tabela_A.Coluna1 = Tabela_B.Coluna1; ON ta.Coluna1 = tb.Coluna1;
LEFT JOIN 097
O LEFT JOIN estabelece o relacionamento entre as tabelas, retornando as linhas que são comuns entre as duas
tabelas e também as linhas que existem apenas na tabela da ESQUERDA.
No exemplo abaixo, repare que o ID_Produto = 4 não está cadastrado na tabela Produtos (da direita), porém existe na
tabela Vendas (da esquerda). Portanto, foi retornado na tabela Final, mesmo sem ter informações na coluna Produto
(NULL):
O INNER JOIN realiza o relacionamento entre as tabelas e retorna apenas as linhas que são comuns entre as duas
tabelas.
Abaixo, repare que somente os produtos de ID_Produto = 1 e 3 (A e C) foram retornados na tabela Final, pois são os
únicos em comum entre as duas tabelas [pois o ID_Produto = 4 só existe na tabela Vendas, enquanto que o ID_Produto
= 2 (B) só existe na tabela Produtos]:
O RIGHT JOIN estabelece o relacionamento entre as tabelas, retornando as linhas que são comuns entre as duas
tabelas e também as linhas que existem apenas na tabela da DIREITA.
Agora, repare que, além dos produtos de ID_Produto = 1 e 3 (A e C), comum entre as tabelas, também foi retornado na
tabela Final o Produto B, por estar cadastrado na tabela Produtos (da direita), mesmo não existindo na tabela Vendas
(NULL). Já o ID_Produto = 4 não foi retornado, pois só existe na tabela Vendas (da esquerda).
TABELA FINAL
2 B
003 4 40
3 C
Agora, repare que, além dos produtos de ID_Produto = 1 e 3 (A e C), comum entre as tabelas, também foram
retornados na tabela Final o Produto B, por estar cadastrado na tabela Produtos (da direita), bem como o ID_Produto
= 4 por estar cadastrado na tabela Vendas (da esquerda).
Tomando como exemplo nossas tabelas Vendas e Produtos, isso acontecerá quando tanto todos os produtos vendidos
na tabela Vendas também estiverem cadastrados na tabela Produtos, quanto todos os produtos cadastrados na tabela
Produtos tiverem sido vendidos na tabela Vendas. Veja só:
Voltando ao nosso banco de dados Northwind, vamos agora fazer um JOIN para relacionar as tabelas products e
categories.
Neste JOIN, queremos retornar as colunas product_id, product_name, category_id, unit_price (da tabela products) e
category_name (da tabela categories).
Repare que foram retornadas 77 linhas no nosso resultado, que é exatamente a quantidade de produtos cadastrados
na tabela da esquerda: a products. Repare que a coluna category_name, da tabela da direita (categories), também
trouxe as informações que queríamos acrescentar ao nosso resultado, graças ao LEFT JOIN que efetuamos:
Entretanto, como todos os produtos da tabela products estão relacionados a alguma categoria da tabela categories,
assim como cada categoria da tabela categories está relacionada a um ou mais produtos da tabela products, neste
caso, se utilizarmos um INNER JOIN no lugar de um LEFT JOIN, obteremos exatamente o mesmo resultado. Veja só:
Exemplos Práticos 105
Repare também que, se preferirmos, em vez de repetir os nomes das tabelas em todo o código, podemos atribuir
aliases a essas tabelas, e utilizá-los para se referir a elas, deixando o código mais enxuto.
No exemplo abaixo, chamamos a tabela products de p e a tabela categories de c. Dessa forma, em todas as linhas do
código em que foi necessário mencionar seus nomes, utilizamos seus respectivos aliases.
Ou seja: temos dois clientes registrados na tabela customers que nunca efetuaram pedido algum.
Será que conseguimos descobrir quem são esses dois clientes utilizando JOINs?
Vejamos:
Se tentarmos efetuar um LEFT JOIN ou um INNER JOIN, não encontraremos o resultado que esperamos, porque, uma
vez que a tabela orders é a nossa tabela da esquerda:
a) O LEFT JOIN retornaria os 830 registros existentes na tabela orders, ignorando as linhas que aparecessem
somente na tabela da direita (a customers). Portanto, os dois clientes que nunca efetuaram pedidos, não
apareceriam no resultado, uma vez que, obviamente, se eles nunca efetuaram pedidos, não aparecem na tabela
orders (da esquerda), somente na customers (da direita).
b) O INNER JOIN também não retornaria os nomes que queremos, uma vez que seu resultado mostraria somente os
registros em comum entre as duas tabelas (orders e customers). Como os dois clientes que nunca efetuaram pedidos
só aparecem na tabela da direita (customers), não seriam considerados como “em comum” com a tabela da esquerda
(orders) pelo INNER JOIN.
Exemplos Práticos 110
Vamos ver:
Destes, 830 fazem referência aos pedidos da tabela orders, que tem 830 pedidos registrados nela. E os outros 2
registros retornados?
Repare que apareceram os nomes de dois clientes (contact_name) que não possuem informações nas colunas que
foram retornadas pela tabela da esquerda (order_id, customer_id, order_date).
Portanto, Marie Bertrand e Diego Roel são os nomes dos clientes que temos cadastrados na tabela customers (da
direita), mas nunca efetuaram pedidos, portanto, não possuem registro algum na tabela da esquerda (orders).
Exemplos Práticos 112
Mas, por curiosidade, vamos ver se com o FULL JOIN também conseguimos encontrar os nomes desses dois clientes?
Veja que, com o FULL JOIN, também foram retornados 832 registros.
Exemplos Práticos 113
Novamente, destes registros, 830 fazem referência aos pedidos da tabela orders, que tem 830 pedidos registrados
nela. E, verificando ao final do resultado retornado, veremos que os outros 2 registros referem-se aos dois clientes
que nunca efetuaram pedidos:
Como o FULL JOIN é capaz de trazer todas as linhas de todas as tabelas relacionadas no JOIN, ele também conseguiu
nos ajudar a descobrir quem eram esses dois clientes.
JOIN, GROUP BY e ORDER BY – Exemplo Prático 114
Vejamos agora um exemplo de como fazer um JOIN utilizando os comandos GROUP BY e ORDER BY em conjunto.
Vamos supor que a gente queira criar um agrupamento (GROUP BY) que retorne como resultado a quantidade total
vendida (SUM(quantity)) para cada produto (product_name). Além disso, queremos ordenar (ORDER BY) o resultado
do produto mais vendido para o menos vendido (ordem decrescente).
O que temos é a coluna product_id que se relaciona com sua equivalente na tabela products.
Por isso, precisaremos fazer um JOIN para associar as tabelas order_details e products, assim poderemos trazer ao
resultado os nomes dos produtos (product_name) em vez de seu ID (product_id).
JOIN, GROUP BY e ORDER BY – Exemplo Prático 115
Vamos imaginar que nós precisamos fazer o mesmo agrupamento anterior, só que agora devemos considerar somente
os produtos da classe Luxo (ou seja, os produtos com preço acima de R$ 80,00).
Para isso, devemos aplicar um filtro ao nosso código. Qual filtro utilizar: WHERE ou HAVING?
Se temos que primeiro selecionar todos os produtos cujo preço (unit_price) seja acima de R$ 80,00, então precisamos
utilizar o WHERE, que filtra a tabela original. Não temos como utilizar o HAVING, pois ele utiliza o agrupamento já
efetuado e filtra alguma condição nesse agrupamento. Como queremos filtrar uma informação constante da tabela
original (coluna unit_price > 80), devemos utilizar o WHERE.
JOIN, GROUP BY, WHERE e HAVING – Exemplo Prático 121
Portanto, no nosso código, antes do GROUP BY, devemos acrescentar o filtro WHERE:
Repare que, agora, nosso código retornou apenas os quatro produtos cujo unit_price é maior que R$80,00 na tabela
products, efetuando a soma de suas quantidades vendidas, ordenando-os do mais vendido para o menos vendido.
JOIN, GROUP BY, WHERE e HAVING – Exemplo Prático 122
Pensemos em outra situação: e se quisermos, considerando todos os produtos, retornar na tela apenas aqueles que
tiveram mais de 1000 unidades vendidas?
Neste caso, precisaremos primeiro efetuar o agrupamento com a soma da quantidade total vendida de cada produto,
para depois conseguir descobrir quais tiveram mais de 1000 unidades vendidas e retornarmos somente esses
produtos no resultado. Certo?
Portanto, o filtro que precisamos utilizar agora é o HAVING, já que ele é o comando capaz de filtrar o agrupamento.
JOIN, GROUP BY, WHERE e HAVING – Exemplo Prático 123
Sendo assim, no nosso código, após o GROUP BY, devemos acrescentar o filtro HAVING:
Repare que, agora, nosso código efetuou a soma das quantidades vendidas
para cada produto e retornou apenas os 12 que tiveram mais de 1000
unidades vendidas, ordenando-os do mais vendido para o menos vendido.
124
MÓDULO 6
VIEWS
125
MÓDULO 6
Introdução 126
Até aqui vimos como criar diferentes consultas aos bancos de dados. Para isso, aprendemos a utilizar comandos como o
SELECT, o GROUP BY, JOINs, etc.
Mas onde foram parar todos esses resultados que criamos? Eles estão em algum lugar?
Tudo o que fizemos até agora foi apenas visualizar alguns dados das nossas tabelas do banco de dados, nada além disso.
Quando executamos um SELECT e logo em seguida executamos outro SELECT, o resultado do primeiro é perdido.
Nenhuma das consultas que fizemos ficou salvo em algum lugar. Inclusive, diversas vezes precisamos criar as mesmas
consultas, pois elas se perdem a cada novo SELECT, ou quando fechamos uma consulta e abrimos uma nova.
Existe uma solução para conseguirmos salvar essas queries em algum lugar, e esta solução é a View.
Introdução 127
• Uma View (ou, traduzindo, uma exibição), é uma tabela virtual criada a partir de uma consulta a uma ou mais tabelas
(ou até mesmo a outras Views) do banco de dados.
• Ela contém linhas e colunas, assim como uma tabela real. Nela, podemos utilizar comandos como o JOIN, o WHERE, e
diversas outras funções.
• As Views sempre mostram resultados atualizados dos dados, ou seja, uma vez criadas, caso haja alterações no banco
de dados, elas são atualizadas automaticamente.
• Caso o servidor seja desligado (ou o SSMS fechado), a View continua armazenada no sistema.
Através de uma View, conseguimos armazenar uma consulta e acessá-la sempre que precisar, como se fosse uma tabela,
com a vantagem de não precisar recriar esse SELECT do zero.
Introdução 128
São muitas as vantagens de uma View. Abaixo temos algumas das principais:
Sempre que necessário, Ao criar uma View, estamos ocultando Quando criamos Views,
podemos consultar aquela linhas ou colunas da tabela original do estamos poupando o tempo
View, pois ela fica armazenada banco de dados. Desta forma, apenas de recriar vários SELECTs, o
algumas informações relevantes serão
no sistema. que aumenta a produtividade.
visualizadas na View.
CREATE or REPLACE View 129
Vamos supor que fizemos uma consulta às colunas product_id, product_name e unit_price da tabela products e
queremos armazenar essa consulta em uma View para utilizá-la posteriormente.
Imagine que nos esquecemos de incluir a coluna units_in_stock na View, por isso precisamos alterá-la.
Para isso, utilizamos novamente o comando CREATE or REPLACE View, acrescentando a coluna desejada no nosso
SELECT:
Observe o resultado
com a nova coluna
incluída:
Nomeamos nossa View como “vwprodutos”. E se quisermos alterar para “vw_prod”, como fazemos?
Se tentarmos utilizar seu antigo nome, será retornado um erro, pois o sistema entende que aquela View não existe mais:
DROP (IF EXISTS) View 135
O DROP IF EXISTS VIEW primeiro verifica se a View existe: se existir, ele procede à exclusão:
Se ele verificar que a View não existe, retorna uma mensagem de alerta na tela, mas o sistema permanece em execução:
DROP (IF EXISTS) View 136
Neste ponto, o comando DROP IF EXISTS VIEW acaba sendo melhor que o comando DROP VIEW, pois este último não
verifica antes se a View existe:
• Caso a View não exista, é retornado um erro na tela e o sistema é pausado, o que pode ser prejudicial para bancos de
dados funcionando em tempo real:
137
MÓDULO 7
CRUD
138
MÓDULO 7
Introdução, CREATE e DROP Database 139
→ Read: permite ler os dados do banco de dados. Basicamente, foi o que mais fizemos no curso, através do SELECT;
Vamos iniciar este módulo aprendendo a utilizar os comandos CREATE DATABASE e DROP DATABASE para criar e
excluir bancos de dados, respectivamente.
Para que nosso novo banco de dados apareça no menu do lado esquerdo da tela do pgAdmin 4, devemos clicar com o
botão direito sobre Databases e, em seguida, selecionar “Refresh”:
Introdução, CREATE e DROP Database 142
Repare que, agora, o BD Teste apareceu entre os bancos de dados existentes, porém está com uma cor cinza e um “x”
vermelho sobre seu ícone. Isso significa que ele não está conectado. Para utilizá-lo, precisamos conectá-lo. Para fazer
isto, basta clicar sobre ele:
Se quisermos excluí-lo, vamos precisar utilizar o comando DROP DATABASE. Mas antes disso, precisamos desconectá-
lo, pois, se tentarmos excluir um banco de dados que esteja em uso (conectado), o sistema retornará o seguinte erro:
Introdução, CREATE e DROP Database 144
Para desconectar um banco de dados, clicamos com o botão direito sobre seu nome no menu lateral esquerdo e, em
seguida, selecionamos “Disconnect from database”:
1
Confirmamos que desejamos desconectar clicando em “Yes”:
2
Feito isso, podemos executar o comando DROP DATABASE e o banco de dados será excluído:
Damos um novo “Refresh” em Databases, e veremos que o banco de dados Teste realmente foi excluído:
Introdução, CREATE e DROP Database 146
Para os próximos exemplos, utilizaremos um banco de dados chamado Hashtag, portanto vamos criá-lo:
4
1
2
Introdução, CREATE e DROP Database 147
Criado nosso novo banco de dados Hashtag, precisamos abrir uma nova Query associada a ele.
Se continuarmos usando a Query que temos utilizado até agora, os comandos serão executados no banco de dados
Northwind:
Introdução, CREATE e DROP Database 148
Portanto, para criar uma nova Query associada ao banco de dados Hashtag, clicamos sobre o BD Hashtag e, em
seguida, no ícone Query Tool, conforme mostrado abaixo:
1
Introdução, CREATE e DROP Database 149
Feito isso, será aberta uma nova Query em branco associada, desta vez, ao banco de dados Hashtag:
Uma tabela tem como objetivo armazenar informações dispostas em diferentes colunas.
Quando criamos uma nova tabela, precisamos especificar quais são as colunas que essa tabela deve conter.
NUMERIC(M, D): um número decimal. M é o número total de dígitos e D é a quantidade de casas decimais permitidas.
VARCHAR(N): uma string de comprimento VARIÁVEL (pode contar letras, números e caracteres especiais). O
parâmetro N especifica o comprimento máximo da coluna em caracteres.
Sabendo os principais tipos de dados, a criação das tabelas do nosso banco de dados Hashtag seguirá a estrutura
abaixo:
Tipos de Dados, CREATE e DROP Table 153
Se fizermos uma consulta às tabelas alunos, cursos e matriculas que acabamos de criar, veremos que elas estão vazias,
pois ainda não inserimos dados nelas:
Tipos de Dados, CREATE e DROP Table 154
Mas... ainda podemos incluir CONSTRAINTS, ou seja, restrições na criação das tabelas.
Apesar de não serem obrigatórias, as CONSTRAINTS são muito importantes para garantir a integridade de nosso
banco de dados, conforme veremos no tópico seguinte.
Como tais restrições são definidas no momento da criação das tabelas, precisamos excluir as tabelas que acabamos de
criar, para criá-las novamente, desta vez, incluindo as CONSTRAINTS que veremos a seguir.
CONSTRAINTS no SQL são regras (restrições) que podemos definir para as colunas de uma tabela. Essas regras
garantem integridade ao banco de dados, pois é através delas que garantimos que apenas os valores que atendam às
regras pré-estabelecidas sejam incluídos em cada coluna.
Por exemplo:
→ Podemos especificar que uma coluna não pode ter valores nulos;
→ Podemos especificar que uma coluna deverá ser uma chave primária ou chave estrangeira.
→ Etc.
As CONSTRAINTS são usadas para limitar os tipos de dados que serão inseridos.
CONSTRAINTS (Restrições) 156
NOT NULL:
• A Constraint NOT NULL faz com que uma coluna não aceite valores nulos.
• Ela identifica que nenhum valor foi definido, obrigando que um campo sempre possua um valor.
• Dessa forma, uma coluna com restrição NOT NULL não aceita valores vazios.
Agora, vamos refazer as tabelas alunos, cursos e matriculas do nosso banco de dados Hashtag, que havíamos criado e
excluído anteriormente, só que desta vez, aplicando as restrições necessárias:
1
2 Também definimos a coluna ID_Matricula como
a chave primária (PRIMARY KEY) desta tabela.
Esta coluna também acaba sendo do tipo NOT
2 NULL, já que, por definição, uma PK não pode
3 conter valores nulos.
Outro comando que temos é o TRUNCATE. Com ele, conseguimos deletar todos os registros de uma tabela de uma só
vez, mas a tabela continua existindo.
Por fim, utilizamos o comando DROP TABLE para excluir uma tabela.
Porém, atenção: cuidado ao excluir uma tabela que tenha restrições de PRIMARY KEY!
Perceba que, se tentarmos excluir a tabela alunos ou a tabela cursos, será retornado um erro:
DROP (Cascade) 167
Isso aconteceu porque, como a tabela matrículas depende das tabelas alunos e cursos, pois faz referência a elas por
meio das chaves estrangeiras que foram definidas na tabela matrículas, as tabelas alunos e cursos não podem ser
excluídas enquanto as chaves estrangeiras da tabela matrículas existirem.
Assim, ou começamos excluindo a tabela matrículas, para depois excluir as tabelas alunos e cursos, ou utilizamos o
comando CASCADE nas tabelas alunos e cursos:
Com o CASCADE, independentemente da tabela que estivermos excluindo possuir alguma relação com outras tabelas
ou não, ela será excluída, como aconteceu acima com as tabelas alunos e cursos.
DROP (Cascade) 168
Se tentarmos visualizar as três tabelas, veremos que, agora, elas foram de fato excluídas:
SQL
IMPRESSIONADOR
PostgreSQL
Apostila completa