Aprenda MySQL

  • Página Inicial
  • Contato!
  • Tudo sobre MySQL Parte 1!
  • Tudo sobre MySQL Parte 2!
  • Tudo sobre MySQL Parte 3!
  • Tudo sobre MySQL Parte 4!
  • Tudo sobre MySQL Parte 5!
  • Tudo sobre MySQL Parte 6!
  • Tudo sobre MySQL Parte 7!
  • Tudo sobre MySQL Parte 4

    Chaves Estrangeiras e Join

    Quando criamos uma tabela em MySQL, nós temos que escolher uma coisa chamada engine, que é a máquina que vai criar os registros.

    No final de um arquivo SQL você encontrará o engine:

    
    engine = innodb
    
    

    No caso, o Inno DB é uma máquina de criação de tabelas, ou seja, um engine (mecanismo). A principal característica do Inno DB é suportar chaves estrangeiras.

    Outras engines são o MylSAM e o XtraDB. A MylSAM é a mais antiga, mas ela não dá suporte à algumas transações, no caso, as que são ACID, cujo significado são esses:

    No exemplo, temos dois bancos de dados distintos, que tem relacionamento entre si, no primeiro, dados de usuários no banco "gafanhotos", e no outro banco temos cursos. Mas no caso especificado, um usuário do banco gafanhotos poderá escolher um curso do banco cursos.

    Gafanhotos

    No exemplo da imagem, Gafanhotos prefere Cursos, o Gafanhotos é o lado 1, se invertesse, como Cursos é preferido por gafanhotos, Cursos seria o lado um (quem exporta é o lado 1, quem importa é o lado "N").

    O que a gente tem que fazer a chave (como a primária) do lado um (do qual ela vem) e levar para o lado "N", adicionando-a no outro lado, ela não precisa ter o mesmo nome da chave primária de onde ela veio, mas tem que ter o mesmo tipo e mesmo tamanho.

    No exemplo, a chave idcurso do Cursos terá o nome de curso preferido na chave estrangeira Gafanhotos:

    
    use cadastro;
    describe gafanhotos;
    alter table gafanhotos
    add column cursopreferido int;
    
    

    Para adicionar uma chave estrangeira, logo após executar o código acima, você fará isso:

    
    alter table gafanhotos
    add foreign key(cursopreferido)
    references cursos(idcurso);
    
    

    No caso, o foreign key adiciona a chave, e o references é a tabela do qual ele será ligado (importado), o que tá entre parênteses é o nome das colunas respectivas. Dê um describe na tabela e verifique se a chave está como MUL (múltipla).

    
    describe gafanhotos;
    
    

    PS: Podemos já criar a chave estrangeira ao criar a tabela, no caso, na coluna especificada, fazemos assim:

    
    cursopreferido int not null references cursos(idcurso)
    
    

    Vamos fazer um update num cadastro qualquer assim, por exemplo:

    
    update gafanhotos set cursopreferido = '6' where id = '1';
    
    

    Para fazer múltiplos updates, podemos procurar essa opção no próprio PHPMyAdmin e selecionar todos.

    PS: Se tentar apagar uma chave primária que foi exportada pra outra tabela (ou seja, uma chave relacionada), ele não permitirá, por exemplo, isso:

    
    delete from cursos where idcurso = '6';
    
    

    Caso queira apagar uma chave estrangeira, faça assim:

    
    alter table gafanhotos
    drop foreign key gafanhotos_ibfk_1;
    alter table gafanhotos
    drop index cursopreferido;
    
    

    PS: O método acima também serve para excluir outros tipos de índices, como primary_key, unique, etc.

    Para aparecer um outro dado da tabela (que não seja a chave primária, mas outro dado referente à ela), usaremos o join.

    No banco cadastro, digite isso:

    
    select gafanhotos.nome, gafanhotos.cursopreferido, cursos.nome, cursos.ano
    from gafanhotos join cursos;
    
    

    PS: O que tiver com ponto, o do lado esquerdo é o nome da tabela e do direito, nome da coluna.

    No comando acima, dará um erro, pois ele juntará todos os curso, mas para corrigí-lo, usaremos um filtro no join, colocando logo após tudo, a ligação com on as duas tabelas e bancos respectivos, assim:

    
    select gafanhotos.nome, gafanhotos.cursopreferido, cursos.nome, cursos.ano
    from gafanhotos join cursos
    on cursos.idcurso = gafanhotos.cursopreferido;
    
    

    PS: Isso daí só mostrará os que tem dados referentes nas chaves estrangeiras. Também podemos usar inner join nesse caso.

    Para ordenar, basta apenas isso:

    
    select gafanhotos.nome, cursos.nome, cursos.ano
    from gafanhotos inner join cursos
    on cursos.idcurso = gafanhotos.cursopreferido
    order by gafanhotos.nome;
    
    

    Também podemos usar "apelidos" para as tabelas ou colunas com o parâmetro as, dessa forma:

    
    select g.nome, c.nome, c.ano
    from gafanhotos as g inner join cursos as c
    on c.idcurso = g.cursopreferido
    order by g.nome;
    
    

    No geral, o Inner Join não considera cadastros que não tem ligação com chaves estrangeiras. Para tratar estes, usamos o left join, dessa forma:

    
    select g.nome, c.nome, c.ano
    from gafanhotos as g left join cursos as c
    on c.idcurso = g.cursopreferido;
    
    

    No caso acima, o left join escolhe a tabela preferencial, que no caso seria a esquerda (esquerda quem exporta, direita quem importa), não considerar nenhum é o inner. Na verdade, existem várias formas de trabalhar com o join.

    O inner join retorna os registros que são comuns às duas tabelas. É o método mais conhecido:

    
    select * from gafanhotos inner join cursos on gafanhotos.cursopreferido = cursos.idcurso;
    
    

    O left join retorna todos os registros que estão na primeira tabela (a), além dos que são comuns com a segunda tabela (b):

    
    select * from gafanhotos left join cursos on gafanhotos.cursopreferido = cursos.idcurso;
    
    

    O right join retorna todos os registros que esão na segunda tabela (b), além dos que são comuns com a primeira tabela (a):

    
    select * from gafanhotos right join cursos on gafanhotos.cursopreferido = cursos.idcurso;
    
    

    O left excluding join retorna todos os registros da primeira tabela (a), desde que não sejam em comum com a segunda tabela (b):

    
    select * from gafanhotos left join cursos on gafanhotos.cursopreferido = cursos.idcurso where cursos.idcurso is null;
    
    

    O right excluding join retorna todos os registros da segunda tabela (b), desde que não sejam em comum com a primeira tabela (a):

    
    select * from gafanhotos right join cursos on gafanhotos.cursopreferido = cursos.idcurso where gafanhotos.cursopreferido is null;
    
    

    Veja abaixo um exemplo gráfico das SQL Joins:

    SQL Joins

    PS: Não é possível usar full join ou full outer join em MySQL, mas ele existe em outros bancos baseados em SQL.

    Podemos puxar os dados do banco sem usar join, mas ele é menos usado. Veja um exemplo assim:

    
    select gafanhotos.nome, gafanhotos.profissao, cursos.nome
    from gafanhotos, cursos
    where gafanhotos.cursopreferido = cursos.idcurso;
    
    

    No caso acima, o join foi substituído pela vírgula.

    Inner Join com Várias Tabelas

    Como visto anteriormente, cada gafanhoto preferiria um curso, trazendo a chave primária de cursos para gafanhotos com a chave estrangeira.

    Nesse novo exemplo, vários gafanhotos podem ver vários cursos. Nesse caso, o "N" (que ficava em ambos os lados), ficará no meio, e o "Assiste" será um nova entidade, e terá um "1" entre as entidades, assim:

    Gafanhotos 2

    No caso acima, o "Assiste" receberá duas chaves estrangeiras, que serão as primárias de gafanhotos e cursos.

    Para isso, crie uma nova tabela com esse nome, assim:

    
    create table gafanhoto_assiste_curso (
        id int not null auto_increment,
        data date,
        idgafanhoto int,
        idcurso int,
        primary key(id),
        foreign key(idgafanhoto) references gafanhotos(id),
        foreign key(idcurso) references cursos(idcurso)
    ) default charset = utf8;
    
    

    PS: Nem toda chave estrangeira precisa ser do tipo INT, apenas ser do mesmo tipo da chave primária.

    Entenda primeiro a ligação que iremos fazer:

    Gafanhotos

    No caso acima, vários cursos estão sendo assistido por várias pessoas.

    Vamos normalmente cadastrar isso na nova tabela, como novos cadastros, assim:

    
    insert into gafanhoto_assiste_curso values
    (default, '2014-03-01', '1', '2'),
    (default, '2015-12-22', '3', '6'),
    (default, '2014-01-01', '22', '12'),
    (default, '2016-05-12', '1', '19');
    
    

    PS: O default é onde será gerado um dado automaticamente (id).

    Para sabermos quais cursos os alunos estão fazendo na tabela do meio, precisamos fazer as junções, dessa forma:

    
    select * from gafanhotos g
    join gafanhoto_assiste_curso a
    on g.id = a.idgafanhoto;
    
    

    Podemos fazer a filtragem do que desejamos ver também:

    
    select g.nome, a.idcurso from gafanhotos g
    join gafanhoto_assiste_curso a
    on g.id = a.idgafanhoto
    order by g.nome;
    
    

    E para puxar o nome do curso, faremos assim:

    
    select g.nome, c.nome from gafanhotos g
    join gafanhoto_assiste_curso a
    on g.id = a.idgafanhoto
    join cursos c
    on a.idcurso = c.idcurso
    order by g.nome;
    
    

    Criando Tabelas Virtuais (Views)

    Uma exibição/visão (view) é uma tabela virtual baseada no conjunto de resultados de uma consulta SQL.

    Ela contém linhas e colunas como uma tabela real, e pode receber comandos como declarações join, where e funções como uma tabela normal.

    Mostra sempre resultados de dados atualizados, pois o motor do banco de dados recria os dados toda vez que um usuário consulta a visão.

    Veja um exemplo de uso abaixo:

    
    create view curso_2018 as select nome, descricao, totaulas from cursos where ano = 2018;
    
    

    PS: Podemos usar várias combinações, baseadas no select que você deseja consultas, da forma que achar necessário.

    E para visualizar a view, fazemos assim:

    
    select * from curso_2018;
    
    

    Veja outro exemplo mais complexo abaixo:

    
    create view vis_users as select gafanhotos.nome as user, cursos.nome as curso
    from gafanhotos inner join cursos on gafanhotos.cursopreferido = cursos.idcurso;
    
    

    E depois:

    
    select * from vis_users;
    
    

    Com as visões, podemos criar códigos complexos e fazer a consulta das mesmas de forma bem mais simples.

    Podemos também alterar as visões usando o alter, por exemplo:

    
    alter view vis_users as select gafanhotos.nome as user, cursos.nome as curso, cursos.ano as ano from gafanhotos
    inner join cursos on gafanhotos.cursopreferido = cursos.idcurso;
    
    

    E para excluir, fazemos simplesmente assim:

    
    drop view vis_users;
    
    

    Podemos também usar outras combinações, como filtros e ordenações, ao criar as views, por exemplo:

    
    create view alunos_2018 as select g.nome as user, c.nome as cursos from gafanhotos g
    join cursos c
    on g.cursopreferido = c.idcurso where c.ano = 2018
    order by g.nome;