Banco de Dados: Aula 6
Banco de Dados: Aula 6
Banco de Dados: Aula 6
BANCO DE DADOS
AULA 6
Nesta etapa, iremos contemplar os temas mais avançados de um Banco de Dados, abordando a
utilização de estruturas auxiliares, como os índices e as views, também conhecidas como tabelas
virtuais.
Também estudaremos sobre as transações que atuam como um conjunto de operações que
mergulhando no funcionamento das triggers, stored procedures, funções e cursores, os quais são
recursos muito importantes que visam simplificar os procedimentos e as tarefas repetitivas que
Banco de Dados (SGBD) realiza uma ação denominada table scan ou full scan, a qual faz uma
varredura na tabela, ou seja, o SGBD percorre toda a tabela procurando as linhas que atendem ao
filtro definido na consulta. Toda linha analisada que não atenda ao filtro será ignorada.
Vale ressaltar que também existe a tabela heap, que não apresenta nenhum índice. Contudo, na
prática, sua existência é bastante rara, inclusive porque a própria Structured Query Language (SQL)
cria índices implícitos automaticamente para colunas PK (chave primária) e FK (chave estrangeira).
Exemplo: em uma tabela que contém o contato de várias pessoas (nome e e-mail), vamos
nome varchar(50),
email varchar(50));
Perceba que, na criação da tabela Pessoa, não houve a declaração de chave (PK ou FK) ou índice,
Na busca pelo nome Vitória, o SGBD percorre a tabela e compara cada nome armazenado com o
filtro realizado (where nome = ‘Vitoria’). Se a linha corresponder ao filtro, será adicionada ao
conjunto de dados que será retornado, caso contrário, será ignorada. Porém, mesmo que seja
encontrada uma linha correspondente, o SGBD seguirá executando a varredura até o final da tabela,
uma vez que pode haver mais linhas que atendam o filtro.
Também é importante salientar que esse exemplo é executado em uma tabela pequena e, dessa
forma, o impacto desse processo não é muito grande. Contudo, imagine essa consulta em uma
tabela que contenha milhares ou milhões de linhas. Qual seria o impacto de uma consulta que
precisa ler toda a tabela procurando as linhas que correspondem ao filtro? Certamente, isso gera um
alto custo computacional.
Para minimizarmos o impacto usamos os índices, que agilizam a localização e a recuperação das
linhas que correspondem a cláusula where, ou seja, aumentam a velocidade do tempo de resposta de
uma consulta.
Selecione apenas as colunas necessárias, pois isso reduzirá a quantidade de colunas que devem
ser retornadas. Na maioria dos casos, não é necessário o uso do asterisco (*), que é equivalente
a todos, em um select;
Na cláusula where, procure usar filtros nesta ordem: números, datas e horas, textos e, por
execução da consulta;
Quando possível, use a comparação por igualdade e não por faixa de valores, reduzindo, assim,
Utilize índices, principalmente em campos numéricos. Tal recurso auxilia o SGBD a localizar os
dados mais facilmente.
1.1 ÍNDICES
São estruturas que auxiliam na organização e na consulta de uma tabela, as quais têm por
objetivo facilitar o acesso aos dados, otimizando o desempenho das consultas. Com sua utilização,
inclusive, ocorre uma diminuição no número de operações de entrada e saída (I/O), o que acaba
Nos Sistemas Gerenciadores de Banco de Dados (SGBDs) o tipo mais usado de índice é
denominado Balance Tree (B-Tree), sendo representado por estrutura em árvore balanceada, ou seja,
é uma árvore de pesquisa binária em que um nó não pode possuir mais que dois filhos e, além disso,
por ser uma árvore balanceada, significa que um lado da árvore não pode ter mais nós que o outro
lado.
Figura 2 – Representação do índice B-Tree
1. B-Tree clustered – A tabela de dados é organizada pela coluna indexada. Na Structured Query
Language (SQL), ao criarmos uma PK (chave primária), automaticamente será um índice
clustered e, sendo assim, as linhas da tabela são organizadas pela chave primária e não pela
ordem de inclusão. Porém, apenas um índice clustered pode ser declarado em cada tabela e,
pequeno “overhead” (tempo de espera) nas operações de atualização, inserção e exclusão, isso
porque a tabela tem que ser reorganizada pela ordem do índice.
indicação (ponteiros) para as páginas de dados onde estão as informações, ou seja, não há uma
organização por ordem do índice. Além disso, toda coluna FK (chave estrangeira) é um índice B-
Tree non-clustered.
Em colunas que armazenem uma grande variação de valores (faixa de valores), como por
exemplo, uma coluna que contém salários ou data de nascimento;
Quando uma ou mais colunas forem usadas frequentemente em filtros where (PK e FK) ou em
Em colunas que são usadas com operadores de comparação e/ou com as cláusulas between,
1. Criação da tabela – Usa-se a palavra reservada index, seguida do nome da coluna que será
indexada.
nomeColuna1 tipo_dado,
...,
nomeColunaN tipo_dado,
index(nomeColuna));
codigo integer,
nome varchar(100),
email varchar(100),
index(codigo));
on tabela(colunas);
on Contatos(nome);
Para demonstrar o uso do índice, vamos realizar algumas consultas com e sem a utilização de
índices.
Exemplo: Projetar os funcionários que possuem salários superiores a R$5.000,00.
Perceba que o tempo gasto para a execução da consulta resultou em 0.0022 segundos.
A seguir iremos criar um índice para a coluna ‘salarioFunc’, realizando a mesma consulta feita
anteriormente e verificando se houve alteração no tempo de execução.
on funcionario(salarioFunc);
1.2 VIEW
Também conhecida como tabela virtual, uma view é um objeto que retorna um conjunto de
dados de uma consulta armazenada em um Banco de Dados. Como possui colunas de tabelas “reais”,
ela pode receber comandos de declarações join, where e funções, como se fosse uma tabela normal.
Além disso, pode ser usada em comandos insert, update e delete para atualização de dados. Onde
aplicar?
Em um conjunto de tabelas que podem ser unidas a outros conjuntos de tabelas com a
recuperadas do select.
view.
with check option Para realizar alterações nos dados de uma view, a
(respeitada).
from information_schema.tables
Exemplo: uma empresa necessita disponibilizar as informações (nome, gênero, salário e e-mail)
dos funcionários para o Departamento de Marketing. Ocorre que essas informações, principalmente
o salário, são restritas e, dessa forma, seria mais seguro e apropriado criarmos uma view que conterá
generoFunc as ‘Genero’,
salarioFunc as ‘Salario’,
3. Usar a view.
1.3 TRANSAÇÕES
Caracteriza-se por ser um conjunto de operações em sequência, as quais são executadas como
um bloco único e indivisível, com início e fim (término), sendo o término definido pela presença de
existir a garantia da integridade de todos os dados ou nenhum dado novo será adicionado ao Banco
de Dados. Isso quer dizer que todas as operações declaradas na transação serão finalizadas com
sucesso ou, então, descartadas. Tipos de transações:
Atomicidade:
o Princípio do “tudo ou nada”, evitando que falhas possam deixar a base de dados
inconsistente.
Consistência:
Ao término de uma transaçãom todos os dados devem estar em um estado consistente
Isolamento:
o Garante que uma determinada transação não usará dados em um estado intermediário,
ou seja, dados oriundos de instruções que tenham sido executadas, mas não confirmadas;
Durabilidade:
o Uma vez encerrada a transação, as alterações por ela efetuadas são definitivas;
o Significa que os resultados de uma transação, caso ela seja concluída com sucesso,
[comandos]
[commit / rollback]
Onde:
Leitura suja (dirty read) – Ocorre em uma transação que acessa dados não confirmados, ou seja,
que estão sendo atualizados por outra transação, o que pode gerar dados incorretos;
Leitura não repetida (nonrepeatable read) – A transação acessa o mesmo dado várias vezes e
Leitura fantasma (phantom read) – Ao ler um conjunto de linhas da tabela, a transação obtém
uma quantidade diferente de linhas em cada leitura;
Atualização perdida (lost update) – Duas ou mais transações consultam a mesma linha e a
Para evitar os problemas de concorrência, pode ser definido um nível de isolamento para as
transações. Tal mecanismo de isolamento é conhecido como lock (bloqueio), onde é definido os
níveis de isolamento que podem ser classificados em:
comandos insert, update e delete permanecem bloqueados para outras sessões até que a
transação seja concluída;
Repeatable read – Não é possível, por uma transação, ler dados que não foram confirmados por
outras transações e nenhuma outra transação pode modificar dados que foram lidos pela
É importante salientar que quanto maior o nível de isolamento menor o número de transações
que serão executadas ao mesmo tempo, o que impacta diretamente no desempenho do Banco de
Dados.
Para exemplificarmos o funcionamento de uma transação explícita, iremos incluir uma linha na
tabela Funcionário, executando o comando rollback para descartar essa inclusão.
-- Continuação
rollback; -- Descarte
Ressaltamos a importância do uso de transações, uma vez que seu principal objetivo é manter a
integridade das informações armazenadas no Banco de Dados. Ao executarmos um conjunto de
operações encadeadas (transações), ou seja, que possuem dependência uma da outra, teremos a
garantia, em caso de erro, que as mesmas serão descartadas, mantendo, assim, os dados íntegros.
Agora que você aprendeu sobre índices, views e transações, exercite esses conceitos nas tabelas
do nosso estudo de caso. Dessa forma, você colocará em prática o conteúdo estudado. Nota: em
cada seção dedicada a um novo comando, as tabelas que estão sendo utilizadas como base para a
execução dos exemplos serão sempre atualizadas com os mesmos dados originais, a fim de evitar
TEMA 2 – TRIGGER
disparou a sua execução. O padrão SQL ANSI define dois tipos de triggers:
1. Em nível de linha – O disparo da trigger ocorre para cada linha inserida, excluída ou atualizada.
Por exemplo, se 10 linhas forem excluídas em uma tabela, a trigger será executada 10 vezes.
2. Em nível de instrução (comando) – A trigger é executada uma vez por instrução. Considerando a
mesma situação anterior, a trigger será disparada somente uma vez.
{momentoDisparado}{eventoDisparado}
on nomeTabela
begin
/* Código da trigger */
end;
Onde:
As triggers são executadas em conjunto com os comandos insert, update e delete. Para que uma
trigger possa acessar as linhas (registros) que estão sendo manipuladas, é necessário fazer uso das
referências new e old, as quais são declaradas conforme o tipo de comando utilizado, sendo:
Comandos úteis:
[where = condição];
Exemplos:
Exemplo: Primeiramente iremos implementar uma tabela Auditoria para as operações realizadas
acao char(10),
matricula int,
dataOperacao date);
on funcionario
for each row
begin
curdate());
end$$
delimiter;
Perceba que estamos criando uma trigger que será disparada após (after) o comando insert na
tabela Funcionário (on funcionario), inserindo os dados na tabela Auditoria e buscando os dados na
referência new das colunas do funcionário que está sendo incluído (new.matricula e
new.salarioFunc).
-- Incluir funcionário
‘ana.rosa@email.com’, 1);
delimiter $$
begin
end$$
delimiter;
where matricula = 1;
Nessa trigger, estamos utilizando as duas referências, new e old. A referência new armazena o
novo salário do funcionário, enquanto que a old contém o salário antigo do funcionário. Assim,
Agora nos falta desenvolver a trigger que irá fazer o controle de auditoria no momento da
exclusão de uma linha.
delimiter $$
create trigger funcionarioExclusao after delete
on funcionario
begin
end$$
delimiter;
insert.
Exemplo de trigger before: vamos criar uma trigger para implementar o autoincremento na
coluna ‘matricula’. Nesse caso, é necessário calcular o número da matrícula antes da linha ser
delimiter $$
create trigger funcionarioNovoID before insert
on funcionario
begin
from funcionario);
end$$
delimiter;
1, 2, ‘tales.heitor@email.com’, 1);
Agora que você aprendeu sobre trigger, exercite esse conceito nas tabelas do nosso estudo de
caso. Dessa forma, você colocará em prática o conteúdo estudado.
Conjunto de instruções da Structured Query Language (SQL) a serem executadas pelo Sistema
Gerenciador de Banco de Dados (SGBD) para realizar uma determinada tarefa. Em seu interior, são
declaradas instruções de seleção, controle e repetição, podendo realizar alterações nos dados
armazenados nas tabelas, porém sem retorno de valores. Também podem ou não receber parâmetros
de entrada.
São usadas para realizar tarefas diárias, repetitivas em um Banco de Dados, como por exemplo,
Utiliza comandos de comparação, comandos de repetição (loop), variáveis e funções. Além disso,
podem ser executadas pelas linguagens de programação. Algumas vantagens de usar procedures são:
Sintaxe: delimiter $$
/* Bloco de comandos */
end $$
delimiter;
Onde:
Tipos de parâmetros:
inout – Combinação de in ou out, indicando que o parâmetro pode ser informado na chamada
Comandos úteis:
1. Mostrar as procedures.
ou
select * from information_schema.routines
2. Excluiras procedures.
[else comandos]
end if
2. Case: Compara um valor com várias condições até encontrar uma verdadeira. Caso não exista
correspondência, o comando else será executado.
[else comandos]
end case
comandos, sendo a instrução finalizada com ponto e vírgula (;). A sintaxe de cada comando é:
Loop – Normalmente usamos os comandos iterate para retornar ao início do loop ou leave para
finalizar o loop.
Sintaxe: [identificador:] loop
/* Bloco de comandos */
if condição then
end if;
leave [identificador];
While-do – O bloco de comandos será executado enquanto (while) a condição for verdadeira.
Esse comando pode não ser executado se a condição for falsa desde o início. O teste da
/* Bloco de comandos */
Repeat-until: O bloco de comandos é executado até (until) que a condição se torne verdadeira.
O teste da condição é realizado no final, assim, o comando é executado pelo menos uma vez.
/* Bloco de comandos */
until condição
Exemplo: vamos criar uma procedure para gerar aleatoriamente 6 números para uma aposta de
loteria. O intervalo dos números será informado como parâmetro na procedure. Os números gerados
concurso int,
numero int);
delimiter $$
nroInicial int,
nroFinal int,
nroConcurso int)
begin
geraNumero: loop
+ nroInicial);
set i = i + 1;
end $$
Perceba que utilizamos o comando loop para implementar o bloco de repetição, sendo que isso
foi proposital. O loop é diferente dos comandos while e repeat, inclusive é necessário criar um
identificador do bloco, nesse caso, o “geraNumero”.
Para cada repetição do bloco, é gerado um número aleatório entre o intervalo informado na
chamada da procedure (‘nroInicial’ e ‘nroFinal’). Além disso, verificamos se o número gerado não
existe e, somente nesse caso, gravamos na tabela e incrementamos o contador (variável ‘i’). Enquanto
o contador for inferior a 6, retornamos para o início do bloco (iterate) ou, caso contrário, encerramos
o bloco de repetição (leave).
Agora que você aprendeu sobre o comando loop, vamos mostrar um trecho de procedure com
Script while:
Figura 16 – Procedure com while
Script repeat:
Agora que você aprendeu sobre procedure, exercite esse conceito no nosso estudo de caso.
Uma função desenvolvida pelo usuário é sintaticamente semelhante a uma stored procedure,
porém, ao final da execução, sempre retornará um valor ou um conjunto de valores de qualquer tipo
de dado válido. Além disso, uma função tem como objetivo suprir tarefas específicas (como por
exemplo, separar o ano de uma data), enquanto uma procedure é mais abrangente (como por
exemplo, tratamento dos dados de uma planilha no Excel, realização de backup, entre outras tarefas).
Basicamente, uma função é um segmento de código (rotina em SQL) que recebe parâmetros de
entrada, processa as instruções definidas e retorna ao ponto de chamada com um resultado.
Você pode estar se perguntando: qual o motivo de trabalharmos com esse recurso? Ao longo do
seu trabalho na área de Banco de Dados, você irá perceber que existem situações que o MySQL não
oferece suporte (de forma nativa) e, assim, surgirá a necessidade de criar suas próprias funções.
No MySQL, existem dois tipos de funções definidas pelo usuário, as quais são:
Sintaxe: delimiter $$
parâmetroN tipo_dados)
begin
instruções
return valor
end $$
delimiter;
Onde:
parâmetros.
instruções Código que a função deve executar, declarado entre o begin
e o end.
Apresentando funções:
Como uma função definida pelo usuário também é um objeto no MySQL, a partir de sua criação,
a mesma pode ser visualizada na ferramenta que estamos usando (MySQL Workbench, item
ou
insert, update, delete, entre outros) em conjunto com o nome da função desejada e a declaração dos
parâmetros de entrada necessários, os quais são definidos na função.
from nomeTabela;
Exemplo 1: vamos criar uma função que retorne se um número é par ou ímpar. Para isso,
usaremos a função mod, que retorna o resto da divisão. Assim, ao dividir um número por dois, se o
resto resultar em zero indica que o número é par.
delimiter $$
begin
end if;
return (tipo);
end $$
delimiter;
Exemplo 2: Vamos criar agora uma outra função que retorne a idade de um funcionário. Para
isso, usaremos a data atual subtraindo da data de nascimento e retornaremos à idade do funcionário.
delimiter $$
begin
return idade;
end $$
delimiter;
Lembra da procedure que criamos anteriormente? A procedure que gera os números para um
concurso da loteria? Dentro da procedure existe uma instrução para gerar os números de forma
aleatória, instrução essa que poderíamos retirar da procedure, criando uma função contendo essa
instrução e, assim, na procedure apenas chamaríamos a função. Vamos ver como se faz?
delimiter $$
begin
return numero;
end $$
delimiter;
ou
TEMA 5 – CURSOR
Ao executarmos um comando select, update ou delete em uma tabela do Banco de Dados, várias
linhas são acessadas de uma só vez. Obviamente, o conjunto de registros retornados depende do
tamanho da tabela e da forma como foi consultada, juntamente com a cláusula where, que filtra os
dados selecionados.
Existem situações em que trazer os registros de uma só vez não é uma forma conveniente ou
possível para realizar certos tipos de operações, uma vez que pode existir a necessidade do resultado
linha a linha.
bastante interessante, chamado de cursor, o qual consiste de uma instrução select por meio de um
laço (loop, while ou repeat) e comandos específicos para cursores, realizando o acesso linha a linha ao
Tal instrução manipula o resultado do select, alocando uma variável na memória com o resultado
obtido por meio da consulta. Dessa forma, permite a realização de operações (atualização, exclusão
ou movimentação de dados) sobre linhas individuais de um resultado. Geralmente, são utilizados em
Um cursor é somente para leitura, não sendo possível realizar diretamente atualização ou
A leitura dos dados por meio do cursor ocorre sequencialmente, isto é, não é possível pular, e
No MySQL, o cursor pode carregar os dados na memória criando uma tabela temporária (cópia)
ou, ainda, apontar diretamente para o conjunto de dados obtido na consulta (asensitive).
Etapas para utilização do cursor: para o pleno funcionamento do cursor, existe um ciclo de
vida, ou seja, uma sequência de etapas que devem ser criteriosamente obedecidas, as quais são:
Onde:
cursor.
Nota: Como boa prática, recomenda-se que a criação de um cursor no MySQL seja sempre
realizada por último, ou seja, declarando todas as variáveis que serão necessárias antes do cursor.
Abrindo um cursor: depois que criamos um cursor, para utilizá-lo é necessário requerer a
abertura do cursor, identificando o mesmo por um nome.
into.
procedimento, uma vez que o número de colunas recuperadas pela instrução select deve
corresponder ao número de variáveis de saída especificadas na instrução fetch.
Vale salientar que mesmo que um cursor tenha sido fechado, não será necessária uma nova
declaração para ativá-lo novamente, sendo apenas necessário executar o comando open para reabrir
o cursor.
disponível. Caso isso ocorra e não houver uma ação predefinida, o cursor fechará e não retornará os
dados.
Para minimizar esse tipo de erro, é importante tratarmos de forma apropriada com a
predefinição de uma ação, a qual será executada se uma linha estiver indisponível. Para isso,
utilizamos a instrução declare handler, que trata de avisos ou exceções.
Onde:
A ação pode assumir dois estados, isto é, manter a execução com a ação continue ou finalizar a
Exemplo: A empresa solicitou uma simulação de reajuste para salários dos funcionários e, sendo
assim, criaremos um cursor que possibilite fazer essa simulação, cujas regras são:
Normalmente, o cursor é declarado dentro de uma procedure e, por esse motivo, criaremos uma
procedure que conterá o cursor com os dados dos funcionários (nome, departamento e salário atual).
Após calcularmos o novo salário do funcionário, armazenaremos em uma nova tabela o nome, o
salário atual e o novo salário.
nome varchar(100),
delimiter $$
begin
open cursorFuncionario;
leCursor: loop
else
close cursorFuncionario;
end $$
delimiter;
Perceba que declaramos um cursor (cursorFuncionario) que contém três colunas no select
(nome, departamento e salario). Dessa forma, necessitamos ter o mesmo número de variáveis
cursor (fetch).
Também declaramos uma variável ‘done’ do tipo boolean, a qual é usada pelo handler para
controlar o final do cursor. Após a leitura linha a linha, quando chegar ao final do cursor, o handler irá
alterar o valor da variável ‘done’ para verdadeiro. Assim, saberemos que chegamos ao fim do cursor,
saindo do bloco de leitura do mesmo.
Como já comentado, apenas após a declaração do cursor é possível a sua abertura (open) para
que possamos manipular os dados que estão armazenados nele. Também já sabemos que um cursor
pode possuir zero ou várias linhas e, assim, devemos usar um comando de repetição para realizar a
leitura linha a linha até terminar. O comando para realizar essa leitura é o fetch.
exercitando esse novo conceito no nosso estudo de caso. Dessa forma, você colocará em prática o
conteúdo estudado.
FINALIZANDO
Ao longo deste estudo, aprendemos muito sobre Banco de Dados. Percorremos diversos temas,
estudando e aplicando conceitos de forma prática, simulando situações do cotidiano, discutindo
sobre assegurar a integridade e a segurança dos dados, tanto na aplicação de protocolos e restrições
quanto também com boas práticas, ressaltando sempre a necessidade de estarmos atentos ao
manipularmos um Banco de Dados.
Gostaríamos de expressar o grande prazer que foi poder compartilhar conhecimento e fazer
parte desse momento de aprendizado. Esperamos que de forma simples e honesta tenhamos
contribuído em seu caminho, fornecendo subsídios para que você possa se tornar um profissional
com espírito crítico e em constante desenvolvimento.
Para você que respira informação, perceba que está ingressando ou já atua no melhor segmento
do mercado, sendo responsável por fornecer a estrutura e suporte para todas as demais áreas. Então,
sinta-se orgulhoso de fazer parte desse seleto grupo de pessoas tão necessárias para o perfeito
REFERÊNCIAS
2023.