Escolar Documentos
Profissional Documentos
Cultura Documentos
MYSQL
Do básico ao avançado
Amazon Press.
Aprendendo banco de dados com mysql
Do básico ao avançado
Jorge Costa Leite Júnior
1a Edição - Salvador/BA
Novembro de 2021
Ficha catalográfica
ISBN: 978-65-00-35482-9
CDU: 004.65 / 42
Nenhuma parte deste livro pode ser reproduzida ou armazenada em um sistema de recuperação,
ou transmitida de qualquer forma ou por qualquer meio, eletrônico, mecânico, fotocópia, gravação ou
outro, sem a permissão expressa por escrito da editora.
ISBN: 978-65-00-35482-9
Dedico este livro a todas a pessoas que pude aprender um pouco nessa vida. Todos
aprendemos com todos, ninguém é incapaz de ensinar ou aprender. Este livro é dedicado a
meus pais, irmãos e amigos. Também a todos os meus estudantes, com suas dúvidas e
inquietações me desafiaram a produzir esta obra com o propósito de ajudá-los no seu
progresso nesta área da Computação, em especial, Banco de Dados.
agradecimentos
Que um pouco desse aprendizado possa ser útil a quem ler este livro.
Além do que foi dito, este livro tem como objetivo atender (e subsidiar)
à quatro públicos distintos. Primeiramente, estudantes de cursos técnicos de
Informática e áreas afins (normalmente do Ensino Médio), cuja literatura
normalmente é de livros de cursos superiores, dificultando, nos casos e
modelos apresentados uma compreensão dos conceitos adequados. O
segundo grupo é o de alunos de graduação de Ciência da Computação, de
Informática ou cursos semelhantes. Um terceiro público é o de usuários de
SGBD pessoais, que desejem sistematizar o projeto de seus bancos de
dados, que vão desde a criação de tabelas, consultas avançadas até o uso de
gatilhos (triggers). Um quarto público, são de meus colegas docentes, que
possam ter passado por desafios semelhantes aos meus, necessitando de
uma literatura mais adequada aos seus grupos de estudantes, com uma
linguagem mais simples e mais modelos e exercícios práticos,
especialmente nos cursos profissionalizantes de Informática e afins.
Prefácio
Índice
Página do título
Aprendendo banco de dados com mysql
Direitos autorais
Dedicatória
agradecimentos
Epígrafe
Apresentação
Prefácio
1. Introdução
2. Bancos de dados
3. Um pouco sobre o uso do MySQL
4. Explorando um banco de dados real
5. Como Modificar dados de um banco?
6. Criando nossos próprios bancos e tabelas
7. Ampliando nossos conhecimentos sobre o Select, Delete, Insert e
Update
8. Junções de tabelas
9. Visões (Views) ou visualização de dados de tabelas
10. Procedimentos Armazenados no servidor – Stored Procedures
11. Programação estruturada em PL/SQL
12. Funções armazenadas ou Functions
13. Gatilhos ou Triggers
Sobre o autor
1. Introdução
Essa questão pode ter várias respostas filosóficas, mas aqui no nosso
contexto, conhecimento é como eu trabalho (técnicas, abordagens, etc.) o
conjunto de informações disponíveis para solucionar uma situação-
problema.
Os Bancos de dados ou Base de Dados (BD) são conjuntos de dados que
contém informações ou registros sobre coisas (objetos da realidade),
pessoas, lugares, situações. São organizados de tal forma, a dar sentido ao
conjunto de dados correlacionados. Isso significa que um BD de uma
clínica é completamente diferente de um BD de uma escola, já que o
conjunto de dados e a forma como se relacionam, e seu propósito são
completamente distintos, pois os dados ali representam uma realidade do dia
a dia completamente diferente entre uma escola e clínica.
Uma pergunta que pode surgir é: “basta ter uma tabela ou planilha para
termos um banco de dados?”
A resposta para esta pergunta não é tão simples, mas podemos ter banco
(ou base) de dados com apenas uma tabela (ou entidade) ou dezenas delas,
dependendo do problema ou situação modelada para o qual o banco de dados
foi projetado. Mas sim, podemos ter bancos de dados com várias tabelas que
se relacionam entre si com propósitos específicos. Na figura a seguir vamos
ver uma representação de um banco de dados com várias tabelas.
Esses são apenas alguns tipos de dados possíveis. Ao longo deste livro,
vamos apresentar tipos diferentes de dados, os quais podem ser utilizados em
diferentes cenários de dados.
1.
Separar dados da aplicação cliente, evitando a mistura de dados e
programa, permitindo compartilhamento de dados
2. Prover uma interface (gráfica, normalmente) para que os usuários
possam incluir, alterar, remover ou consultar dados já armazenados
3. Controlar o acesso aos dados, aumentando a segurança
4. Simplificar ao programador e usuário uma forma de projetar e
visualizar a estrutura de dados (modelo) para o BD através de
ferramentas de gestão, modelagem e manipulação de dados.
Questões Teóricas
Instalação do MySQL
Para criar outros usuários basta clicar em ADD USER e uma janela vai
aparecer permitindo a criação desse novo usuário e seu perfil de acesso,
conforme a figura 3.2.
Figura 3.2 – Tela de criação de novos usuários
Uso do MySQL
MySQL Workbench
Primeiros Comandos
Para executar esse comando, lembrando que deve terminar com; temos
duas opções: usar o atalho Ctrl+ ENTER ou clicar no ícone do Flash
(trovão) com o cursor significando que só executará aquele conjunto de
comandos selecionado.
-- isso é um comentário
/* isto também é um comentário */
Questões teóricas
Uma vez que conhecemos o banco e suas tabelas vamos agora instalar e
configurar o banco no servidor. Após o download do script [aqui] e o mesmo
salvo no seu sistema de arquivos (bancotimes.sql), vamos abrir e rodar o
script clicando na pastinha azul (ícone que representa o carregamento de
script em tela), como se pode ver na figura 4.2.
Describe jogadores;
Depois nos conte o que percebeu. A pergunta que nos vem agora é:
“onde estão os dados?”
Vamos ao resultado:
Uma pergunta a seguir seria: "tem uma forma de filtrar os dados que
quero exibir?"
Por exemplo: Times que foram fundados depois de 1900. Nossa pergunta
poderia ser formulada assim: “Mostre todos os times onde ano de fundação
seja maior que 1900?”
Sendo assim precisamos aprender uma palavra nova: WHERE (no bom
português, significa “onde”). Alguns estudantes novatos gostam de associar
tal comando a um IF (SE) das tradicionais linguagens de programação.
Traduzindo para nosso SQL teríamos:
Observe que o time Flamengo saiu da lista exibida, uma vez que, sua
fundação é anterior a 1900, conforme resultados exibidos (figura 4.8). Uma
pergunta possível é se o Flamengo deixou de existir no banco de dados. A
resposta seria não. O comando SELECT serve somente para exibir dados
cadastrados. Ele não apaga dados.
Agora que vimos dados dos jogadores, vamos fazer algumas perguntas:
1. Mostre jogadores que ganham mais de 3000 ou menos de 2000.
Figura 4.11 – Uso do conectivo OU (OR) na cláusula WHERE
Questões Teóricas
Questões Práticas
O primeiro passo para trabalhar com esse banco é executar seu script de
criação disponível Aqui.
O Comando INSERT
Uma dica antes de inserir dados numa tabela, é verificar quais são seus
atributos e restrições de dados. Sendo Assim, precisamos revisitar o
comando DESCRIBE.
O Comando DELETE
Vou explorar aqui os casos nos quais excluímos registros pela chave
primária. Sendo assim o comando DELETE ficaria assim: delete from
tabela where chaveprimaria=valor;
Por exemplo, quero excluir o time Barcelona, e já sei que o valor da
chave primária é 8, logo meu comando seria assim: delete from
times where idtimes = 8;
Em outras palavras, você não pode excluir um time que ainda tem
jogadores associados a ele por chave estrangeira. Acredite, esse erro é
comum em novos programadores, muitas vezes por displicência do
programador SQL.
O Comando UPDATE
where idtimes = 1;
Esse comando vai alterar o nome do Bahia para Novo Bahia e seu valor
para 10000000. Observe que o update foi feito com o critério da chave
primária. O resultado após modificação pode ser visto na figura 5.3:
Questões Teóricas
Exercícios de tradução
Questões Práticas
Nosso banco de dados agora está criado. Para usar o banco retomamos
ao famoso USE NOMEDOBANCO;
CRIAÇÃO DE TABELAS
Observe que as modificações nos atributos são bem diversas das listadas
na figura 6.7. Vale destacar que se a tabela estiver preenchida com dados,
pode haver perda de dados, problemas de conversão de tipos e outros erros.
Portanto, é preciso cautela ao usar ALTER TABLE e suas variantes com o
banco de dados em produção.
Questões teóricas
Questões Práticas
Uma vez executado o script, o banco e tabelas serão criados com todos
os seus dados (conforme figura 7.2). Feito isso, vamos numa sequência de
comandos selecionar o banco (verifique o nome correto do banco no script) e
exibir as tabelas (figura 7.3):
Feito isto, temos nosso banco criado e vamos examinar algumas tabelas.
Podemos dar um DESCRIBE em cada tabela ou usar um SELECT para
vermos os dados. Vou mostrar dois exemplos a seguir (figuras 7.4 e 7.5):
Para resolver esse problema precisamos entender primeiro, que por uma
questão de modelagem, se prefere guardar o idpacientes na tabela
CONSULTAS. O motivo para isso é para que se evite o problema de
inconsistência nos dados, além de minimizar o uso recorrente do atributo
nome na tabela
CONSULTAS, evitando que o usuário em processos de
digitação para um mesmo nome, digite (de maneira errada ou despropositais)
nome errado para um paciente já cadastrado.
Uma resposta simples seria fazer a boa e velha consulta básica: select
nome, sexo, idpacientes from pacientes where
idpacientes =1;
Como posso juntar a reposta para essas duas questões em uma única
consulta?
Para resolver essa questão, vamos voltar para a boa e velha teoria de
conjuntos. Já sabemos que o atributo idpacientes está em dois conjuntos ou
tabelas diferentes associadas. Nossa pergunta, dentro dessa perspectiva se
tornaria algo do tipo:
Conjunto B:
Como se pode ver na figura 7.12, o filtro (cláusula WHERE) serviu para
selecionar e filtrar pelo idpacientes (elemento associativo) para verificar a
pertinência (não) de um elemento do CONJUNTO A (o primeiro select) no
SUB-CONJUNTO B (segunda consulta). Observe que a sub-consulta é
dada dentro de parênteses.
Uma vez detalhando esses tipos de dados a resposta a esta consulta seria
a representada na figura 7.14:
Figura 7.14 – Consulta com intervalo de datas
1. select sabor, preco from pizzas where sabor like ‘%a’ order by preco
desc; 2. select idatendentes, idsocios, datapedido, valor_total from pedidos
where valor_total > 45 and datapedido between ‘2017-01-01’ and ‘2017-12-
31’; 3. select sabor, preco, quantidade from pizzas where preco < 45 and
quantidade < 100; 4. select count(idsocios), idtiposocio from socios group
by idtiposocio; 5. select idatendentes, idsocios, datapedido, valor_total from
pedidos where idatendentes = 1 order by datapedido; 6. select
sum(valor_total), idatendentes from pedidos group by idatendentes;
Questões Práticas
1. INNER JOIN
2. RIGHT JOIN
3. LEFT JOIN
Vamos começar pelo INNER JOIN, que equivale a uma interseção de
conjuntos. Isso significa que um elemento deverá estar nos dois conjuntos de
dados (tabelas ou resultados de consultas). Se observarmos o modelo, temos
o atributo idpacientes nas tabelas PACIENTES e CONSULTAS. Como
chave primária na primeira tabela (vamos chamar de tabela1) e chave
estrangeira na segunda tabela (vamos chamar de tabela2), esse atributo serve
como forma de associação entre esses conjuntos de dados. Deste modo,
precisamos para todo processo de junção de tabelas seguir os seguintes
passos:
Vale ressaltar que o MySQL permite juntar até 16 tabelas numa mesma
instrução. É possível, que com a evolução do SGBD tais limites sejam
modificados. Vamos apresentar exemplos crescentes de junção de tabelas
com duas ou várias tabelas.
Para resolver essa questão, vamos para cada passo. Os atributos e tabelas
envolvidos são: pacientes.nome, consultas.dia, consultas.hora. Ressaltamos
que as tabelas envolvidas são CONSULTAS e PACIENTES.
Observem, que os passos 3, 4 e 5 não são usados, uma vez que não
tivemos filtros (WHERE), agrupamentos (GROUP BY), ou ordenações
(ORDER BY), passos que são opcionais e depende de cada questão
problema. Para ilustrar essa situação vamos ampliar a questão anterior.
Figura 8.7 – Consulta usando LEFT JOIN com valores nulos (NULL)
Para ilustrar isto ( ver listagem da figura 8.10), vou apenas mostrar o
nome dos médicos nos três casos (sem repetição). Vou aplicar um limitador
para 5 registros, com o comando LIMIT 5;
Observe que foi adicionada (ver na figura 8.15) a junção para a tabela
ESPECIALIDADES com o comando: inner join
especialidades on medicos.idespecialidades =
especialidades.idespecialidades
Usando o mesmo princípio, podemos juntar quantas tabelas forem
necessárias para responder a um questionamento a nossa base de dados.
Para resolver essa questão, precisamos ter em mente que vamos exibir
dados de médico e o nome de doença atendida, que neste caso será gripe
(filtro), desde que o médico tenha mais de 30 anos (filtro). Apesar de
exibirmos dados de apenas duas tabelas, é obrigatório passar pela tabela
CONSULTAS, pois é por meio dela que se associam os dados de doença e
médico. Logo teremos três tabelas envolvidas (MEDICOS, CONSULTAS,
DOENCAS).
Observe que até a seleção de dados representada na figura 8.16, não foi
aplicado filtro (where), mas agora (na listagem da figura 8.17) foram
aplicados os fitros para idade e doença.
Neste cenário, precisamos considerar que até agora não trabalhamos com
busca textual parcial. Para isso, vamos precisar apresentar o operador LIKE
(em português “parecido”). Além disso, é possível que algumas doenças
cadastradas podem ainda não ter consultas realizadas para sua descrição.
Sendo assim, usar INNER JOIN é inadequado. Só usamos INNER JOIN
(considerando que é uma interseção de conjuntos) somente se sabemos que
há consulta para aquela doença. Vamos assim optar pelo uso do LEFT JOIN.
Questões Teóricas
9. Por que, nos casos de junções sem INNER JOIN é comum termos
registros ou linhas de resultados com NULL?
10. Quando usamos funções de agregações, em consultas com uso de
junções de tabelas, é necessário realizar agrupamentos? Se sim, em que
casos?
11. Sub-consultas poderiam resolver problemas que normalmente
solucionaríamos com junções? Cite alguns exemplos.
Questões Práticas
Uma vez que temos certeza de que nossa consulta produziu o resultado
esperado (figura 9.1), vamos a construção da View. Vou chamá-la de
vPacientes. Neste livro vamos usar esse prefixo v (Letra V minúscula
antes do nome da View). É somente uma prática (estilo) pessoal. Não é uma
regra.
Observe que além das tabelas originais do banco, apareceu nossa view
vPacientes como se fosse uma tabela. Exato! Podemos operar com uma
view como se fosse uma tabela. Então vamos usar o comando DESCRIBE
para descrever nossa View?
Figura 9.4 – Descrição de uma View
Observe que comando DROP VIEW é seguido pelo nome da View a ser
apagada (figura 9.6). No nosso caso vPacientes.
Observe que o resultado desta consulta (figura 9.10) trouxe dois atributos
nome (o primeiro para pacientes e o segundo para médico). Caso criássemos
uma View usando na íntegra tal comando teríamos uma “tabela virtual” ou
View com dois atributos de mesmo nome.
Isto provocaria um erro, pois em uma mesma tabela, não é possível ter
dois atributos com mesmo nome, o mesmo vale pra views. Para corrigir isto
vamos usar alias (ou apelido) nos nomes de médicos e pacientes (figura
9.11). Como exibido a seguir:
Figura 9.11 – Aplicando apelidos nas colunas nome de Pacientes e
Médicos
Uma vez que aprendemos o básico sobre views (ou visões), uma
pergunta possível é: “Podemos juntar uma tabela com uma view?”
Veremos a seguir: Exemplo 4: “Aproveitando a visão VConsultasPaciente
exiba o nome da doença atendida.”
Concluímos, então, que é possível realizar junção com visões desde que
tenhamos disponíveis chaves que relacionem as tabelas ou visões envolvidas
na consulta SQL a ser executada.
Questões Teóricas
Exercícios práticos
Por padrão no MYSQL, o modo é IN. Sendo assim, pode ser omitido no
momento da criação do procedimento.
CALL spEditarPaciente('Coisinho
Silva','m',43,'espirros',36);
Questões Teóricas
Exercícios Práticos:
Parte 1 - Crie Procedures para o banco CLINICA que:
1. Cadastre um paciente 2. Edite um paciente 3. Busque as consultas do
paciente pelo nome 4. Cadastre um médico
Agora, para este exemplo vamos testar se o usuário passou algum ano e
nome vazios ou nulos e vamos validar isto.
Questões Teóricas
Exercícios práticos
1.
Receba o nome de um paciente e retorne os dias de suas consultas. O
nome não pode ter menos que 3 caracteres.
2. Cadastre um médico. Valide os dados obrigatórios da tabela.
3. Receba um sexo e mostre os pacientes daquele sexo. Valide os sexos
recebidos com a Estrutura CASE.
4. Busque os médicos de uma especialidade. Valide o nome da
especialidade, evitando nulos e dados vazios.
5. Insira uma consulta médica. Valide os dados obrigatórios da consulta
6. Busque uma doença pelo nome e listar a quantidade de atendimentos
dela. Informar ao usuário caso não a encontre. Use o operador LIKE
na busca
7. Busca todas as consultas realizadas, o nome do médico e do paciente.
Valide se os nomes são nulos ou não, nos parâmetros. Use busca
exata.
8. Exclua um funcionário baseado no seu IdFuncionário. Valide se o
valor passado é nulo ou não. Caso o usuário não exista, informe ao
usuário.
9.
Ao receber o número de um ambulatório, mostre os médicos ali
pertencentes. Valide testando se o número passado é positivo.
10. Mostre um ranking do maior para o menor, número de consultas por
médico, limitando a quantidade de registros ao limite passado por
parâmetro. Dica: Usar o comando LIMIT.
Delimiter $$
CREATE FUNCTION NomeDaFunção (parametro1 tipo1,par ametro2 tipo2,
parametroN tipo)
RETURNS <TIPO>
Begin
< BLOCO DE INSTRUÇÕES PL/SQL>
End;
$$
Até o momento, neste texto, temos duas funções criadas. Podemos listar
as funções criadas pelo comando a seguir:
Figura 12.3 – Listando as funções armazenadas
Caso precise que uma função retorne uma lista ou um conjunto de dados,
programe sua rotina como um procedimento. Por enquanto, é este o
conhecimento que apresentamos até aqui.
Questões Teóricas
Questões Práticas
Parte 1 - Para o BANCO CLINICA e usando os conhecimentos de
Funções Armazenadas, RESOLVA AS QUESTÕES A SEGUIR:
Podemos ter várias triggers num banco de dados, mas apenas uma
trigger por evento. Por exemplo, a tabela T1 só poderá ter uma trigger para o
evento INSERT, outra para o DELETE e outra para UPDATE. Os eventos
geram dados em memória.
E agora finalmente devemos definir quando esses dados vão ser enviados
da tabela T1 para T2. Isto pode ocorrer ANTES (BEFORE) ou DEPOIS
(AFTER) do evento de tabela. De modo geral temos o seguinte:
a) Evento INSERT → Dados NEW. Momento AFTER
b) Evento DELETE→ Dados OLD. Momento BEFORE
c) Evento UPDATE → Podemos ter tanto dados OLD e NEW. E pode
ser disparada nos momentos antes (BEFORE) ou depois (AFTER)
do evento.
A tabela 1
(T1) pode receber eventos (insert, delete, update) nos
momentos de disparo (antes ou depois), produzindo dados novos ou velhos
(NEW, OLD), que serão processados e utilizados nos efeitos produzidos na
tabela 2
(T2) .
Para ilustrar melhor o uso de triggers, vamos trabalhar com alguns cenários e
exemplos.
Essa trigger foi programada para que ao se receber uma ação (evento) de
INSERT na tabela
PACIENTES, sejam registrados alguns de seus dados na
tabela REGISTROPACIENTES. Não há passagem de parâmetros em
gatilhos ou triggers, portanto, apenas operamos com os dados NEW ou OLD
disponíveis com o disparo da trigger.
Vamos agora pedir uma pizza do sabor ‘Baiana’ cujo idPizzas=4 e tem
60 unidades em estoque (atributo quantidade, na figura 13.15). Vamos
adicionar esse sabor a um pedido já existente. Vamos optar pelo
Idpedidos=10;
Figura 13.15 – Dados das pizzas e suas quantidades
b)
Nova quantidade maior que a quantidade anterior. Diminuição do
estoque.
Agora vamos modificar esta trigger. Sua nova versão ficará assim:
a) Criação do pedido:
Essa operação (de inserção ou cadastro do pedido, figura 13.28) não tem
efeito secundário em nenhuma tabela, pois não programamos nenhuma
trigger associada a um INSERT na tabela Pedidos.
Demonstramos por este exemplo que uma trigger pode gerar efeitos em
várias tabelas, desde que planejados adequadamente tais efeitos. Além disso,
pudemos demonstrar o uso de variáveis internas nas triggers por meio deste
exemplo adicional.
Questões Teóricas
Questões Práticas