---
# System prepended metadata

title: Banco de Dados MySQL

---

# Banco de Dados MySQL - Resumo
Resumo baseado nas aulas do Data Bootcamp - Embraer Social Tech Careers

## Comandos mais utilizados
- **status;**
Exibe todas as informações da conexão bem como o database em uso no momento e o usuário logado.

- **\\! cls;**
Limpa a tela do MySQL Command Line Client

- **show databases;**
Exibe os databases existentes.

- **create database nomeDoDatabase**
Cria uma base de dados. 

- **use nomeDoDatabase;**
Permite o acesso e uso da base de dados mencionada no comando.

- **show tables**
Exibe as tabelas existentes na base de dados em uso.

- **desc nomeDaTabela**
Exibe a estrutura da tabela mencionada. Nota: para conseguir acessar a tabela é preciso estar com o banco a qual ela pertence em uso. Também pode ser usado describe ao invés de desc. 

## Criação da Base de Dados
```
create database ecommerce
```
## Acesso à Base de Dados
```
use ecommerce
```
## Criação de Tabelas
```
create table cliente(
    id integer not null auto_increment primary key,
    nome varchar(100) not null,
    email varchar(70) unique,
    senha varchar(20) not null,
    cpf varchar(20) not null unique
);

create table departamento(
    numero integer not null auto_increment primary key,
    nome varchar(30) not null,
    descricao text,
);

create table endereco(
    num_seq integer not null auto_increment primary key,
    tipo varchar(5) not null,
    logradouro varchar(50) unique,
    numero integer,
    complemento varchar(20),
    bairro varchar(30),
    cidade varchar(50),
    estado varchar(2),
    cep varchar(10),
    id_cliente integer not null,
    constraint endereco_cliente foreign key (id_cliente) references cliente(id)
);

create table pedido(
    numero integer not null auto_increment primary key,
    status varchar(1) not null,
    data_pedido date,
    valor_bruto double,
    desconto double,
    valor_liq double,
    id_cliente integer not null,
    constraint cliente_pedido foreign key (id_cliente) references cliente(id)
);

create table produto(
    codigo integer not null auto_increment primary key,
    nome varchar(50) not null, 
    descricao text,
    preco double,
    estoque integer,
    link_foto varchar(255),
    numero_dpto integer not null,
    constraint produto_dpto foreign key (numero_dpto) references departamento(numero)
);

create table item_pedido(
    seq integer not null auto_increment primary key,
    quantidade integer,
    preco_unit double,
    preco_final double,
    codigo_produto integer not null,
    constraint item_produto foreign key (codigo_produto) references produto(codigo),
    numero_pedido integer not null,
    constraint item_pedido foreign key (numero_pedido) references pedido(numero)
);
```

**not null** - Campo não pode ser vazio
**auto_increment** - Campo que será incrementado automaticamente.
**primary key** - Campo classificado como chave primária. O valor deste campo não se repete nos registros da tabela e, então, serve de identificador único para cada registro. 
**unique** - Campo deve ser único diante de todos os registros. Funciona como chave alternativa podendo buscar um registro por este campo também. 
**text** - tipo de dado que aceita até 16k caracteres
**constraint** - Cria uma restrição que precisa ser nomeada, por exemplo: endereco_cliente. 
**foreign key** - Indica que a restrição é para uma chave estrangeira, ou seja, referenciará campo de uma outra tabela. 
**references** - Neste caso, o (id_cliente) vai referenciar o campo (id) da tabela cliente. 
**default 0** - Para campos numéricos onde, quando não indicado seu valor, o valor padrão é zero. 

## Alterações de Estruturas do Banco de Dados
Estes comandos precisam ser planejados cuidadosamente. Alterar ou apagar tabelas podem influenciar no modelo construído. Uma outra tabela pode referenciar a que seria apagada. Inclusive, se a tabela que seria apagada tiver algum relacionamento, o comando não será executado pela primeira vez como alerta. 
```
alter table cliente add column rg varchar(10) not null after senha;

drop table cliente;

drop database ecommercev2;

alter table cliente modify column rg varchar(15);

alter table cliente change column rg registro_geral varchar(10) not null;

```
**alter table** - Comando inicial para alterar uma tabela. 
**add column** - Em conjunto com o alter table, adiciona uma nova coluna na tabela. 
**modify column** - Em conjunto com o alter table, modifica o tipo de dado da coluna já existente da tabela. 
**change column** - Em conjunto com o alter table, altera o nome de uma coluna já existente da tabela bem como seu tipo de dado.
**drop column** - Em conjunto com o alter table, apaga columa da tabela. 
**drop table** - Apaga determinada tabela.
**drop database** - Apaga uma base de dados. 

### Estudo de Caso
Situação: Criada a tabela de Produto com o campo de código apenas como chave primária e not null. Deveria também ter sido criada como auto_increment. 
Criou-se em seguida a tabela item_pedido já com o relacionamento com produto. Então, código da tabela de PRODUTO seria chave estrangeira na tabela de ITEM_PEDIDO. 

Percebido o erro, não foi possível alterar o campo código da tabela produto pois ele mantinha um relacionamento com a tabela de item_pedido. O que fazer: 

```
ALTER TABLE item_pedido DROP FOREIGN KEY fk_pedido_has_produto_produto1;
ALTER TABLE produto MODIFY codigo INT AUTO_INCREMENT;
ALTER TABLE item_pedido ADD CONSTRAINT fk_pedido_has_produto_produto1 FOREIGN KEY (produto_codigo) REFERENCES produto(codigo);
```

## INSERT - Inserção de dados nas tabelas
CRUD - C - Create
Inserindo dados com a definição dos campos, não importando a ordem. Atentar-se ao nome dos campos que devem ser idênticos aos declarados na tabela. 
```
insert into departamento(codigo, nome, descricao) values (1, 'Tecnologia', 'Produtos para computadores');

```
Atenção à ordem da estrutura nas tabelas. A ordem para inserir os dados na tabela deve ser a mesma ordem de definição dos campos da tabela se os campos não foram definidos no comando. 

O campo de código foi definido como auto-increment, portanto, neste caso ele pode ser declarado como vazio e entende-se que o valor não se aplica  e p banco de dados decidirá. 

```
insert into departamento values (null, 'Eletrônicos', 'Tudo o que não é computador e liga na tomada');
```
Também há a possibilidade de inserir mais de um registro em apenas um comando de insert da seguinte forma:

```
insert into departamento values 
    (null, 'Games', 'Para jogadores Hard Level'),
    (null, 'Acessorios', 'Cabos e conectores que a gente sempre perde'),
    (null, 'Alimentação', 'Porque dev não vive só de dogão');
```

Ao inserir um registro na tabela produto, o último campo é o campo de departamento_id. Então, neste caso, teríamos um vínculo entre tabelas. Portanto, é preciso conferir que o valor inserido como departamento_id na tabela produto seja um id existente na tabela de departamentos. Se não houver um departamento com id = 10 cadastrado, a inserção não terá sucesso. 

```
insert into produto values
	(null, 'Computador','Computador cheio de led top de linha', 500.0, 3, './imagens/computador.png', 10);
```
## SELECT - Busca e exibe resultados
CRUD - R - Read

Seleciona todos os dados da tabela departamento.
```
select * from departamento;
```

## UPDATE - Atualiza registro
CRUD - U - Update
Atualiza determinado campo da tabela que cumpra o critério de identificação do campo. 

```
update departamento set nome = 'Informática e Tecnologia' where codigo = 1;
```

## DELETE - Deleta registro
CRUD - D - Delete
Deleta um determinado arquivo da tabela especificada que cumpra o critério de identificação. 
```
delete from departamento where codigo = 1;
```

Tanto no UPDATE quanto no DELETE, é importantíssimo o critério para que não haja maiores intercorrências como atualizar campos indevidos ou até mesmo deletar campos. 

## Consultas Simples
É possível selecionar apenas as tabelas que se deseja exibir. 
```
select id, nome, email, senha, cpf from cliente;
select * from cliente;
```
Recuperando todos os produtos:
```
select * from produto;
```

Buscando produtos por alguma palavra-chave:
```
select * from produto where nome like "%USB%";
```

Recuperando todos os pedidos:
```
select * from pedido;
```

Recuperando o total faturado geral (sem critério algum):
```
select sum(valor_final) from pedido;
```

Buscando quantos clientes ao total:
```
select count(id) from cliente;
```

A mesma consulta acima, mudando o titulo da coluna:
```
select count(id) as 'total de clientes' from cliente;
```

Buscando através de um critério:
```
select * from cliente where id = 1;
```

Ordenando clientes pelo nome:
```
select * from cliente order by nome asc;
```

## Agrupamentos - Group by
Recuperando dados da tabela produtos agrupados de forma que o retorno seja quantos produtos tem de cada departamento. 
```
select  departamento_codigo, count(codigo) as quantidade from produto group by departamento_codigo;
```
Recuperando dados da tabela produtos agrupados de forma que o retorno seja qual o valor total de produtos de cada departamento. 
```
select departamento_codigo, sum(preco*estoque) as 'Valor Total' from produto group by departamento_codigo;
```

## Junções
### Junções com 2 tabelas
Junção simples como produto cartesiano: Traz a combinação entre as duas tabelas, como se uma linha de uma tabela se multiplicasse por todas as linhas da outra. 
```
select * from produto inner join departamento;
```

Agora trazemos a restrição como condição para trazer o que realmente foi modelado. Trazendo a linha do produto somente com o departamento no qual faz parte. 
```
select * from produto inner join departamento on produto.departamento_codigo=departamento.codigo;
```

Junção de uma mesma tabela fazendo uma cópia da mesma para cruzamento dos produtos sem que um produto se cruze com ele mesmo. **Nota**: é possível criar alias para tabelas, não apenas para o que vai ser selecionado. 
```
SELECT 
    produtoA.nome as produtoA, 
    produtoB.nome as produtoB 
FROM 
    produto AS produtoA
INNER JOIN 
    produto AS produtoB
    ON produtoA.nome <> produtoB.nome;
```

Recuperando todos os clientes e seus respectivos endereços
```
select * from cliente inner join endereco on cliente.id=endereco.cliente_id;
```

### Junções com 3 ou mais tabelas
1. Passo 1: encontrando os itens de cada pedido
1. Passo 2: fazer junção com produto
1. Passo 3: fazer a junção com cliente.
```
select * from 
pedido inner join item_pedido 
	on pedido.numero=item_pedido.num_sequencial
    inner join produto on item_pedido.produto_codigo=produto.codigo
    inner join cliente on cliente.id=cliente_id;
```
Mesma consulta anterior, porém buscando todos os dados do pedido + nome do cliente + nome do produto
```
select pedido.*, cliente.nome, produto.nome from 
pedido inner join item_pedido 
	on pedido.numero=item_pedido.num_sequencial
    inner join produto on item_pedido.produto_codigo=produto.codigo
    inner join cliente on cliente.id=cliente_id;
```


### Junções Externas
**Nota**: Fixar e preservar a tabela que deve ser exibidos todos os registros. 

Buscando todos os produtos a partir dos departamentos
```
select * from departamento inner join produto on departamento.codigo=produto.departamento_codigo;
```
Inserindo um novo departamento
```
insert into departamento values (null, 'Móveis', 'Móveis para escritório e gamers de todas as idades');
```
```
select * from departamento;
```
Utilizar uma junção externa (outer join): retorna os registros que contemplam o filtro ON e também os que ficam de fora. No nosso caso, se buscassemos, não traria o departamento de Móveis por nao ter nenhum produto vinculado a ele. Mas agora, ele vai trazer e dizer que não há nada. 
Tabela dominante: departamento. À esquerda. Por isso colocar o left
```
select * from departamento left outer join produto on departamento.codigo=produto.departamento_codigo;
```
Agora usando right outer 
```
select * from produto right outer join departamento on departamento.codigo=produto.departamento_codigo;
```


### Subconsultas - Subqueries
Critério de seleção (where) depende da resolução de outra consulta. 

Buscar todos os pedidos que possuem o produto mais caro do ecommerce
* Como saber qual o produto mais caro? Opções.
```
select * from produto order by preco desc limit 1;
select * from produto having max(preco);
select * from produto where preco = (select max(preco) from produto);
```
* Mas na verdade, preciso dos pedidos que contem este produto.
``` 
select * from pedido inner join item_pedido 
	on item_pedido.pedido_numero = pedido.numero 
    where item_pedido.produto_codigo=(select codigo from produto having max(preco));
```

* Caso eu queira os clientes que compraram este produto mais caro basta fazer na consulta externa uma junção com cliente e recuperar seu nome.
```
select * from cliente inner join pedido on cliente.id=pedido.cliente_id
inner join item_pedido on item_pedido.pedido_numero=pedido_numero
where item_pedido.produto_codigo=(select codigo from produto having max(preco));
```