# 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)); ```