-
Curso de SQL
Uma abordagem com MySQL
Prof. José Augusto Cintra
htttp://www.josecintra.com/blog
Revisão 2 - Julho/2020 – Quarto mês da quarentena
htttp://www.josecintra.com/ead
-
Apresentação
O objetivo deste curso é fornecer conceitos
básicos sobre a SQL, linguagem amplamente
utilizada para manipulação de Bancos de
Dados Relacionais.
Os exemplos aqui apresentados foram testadosno SGBD MySQL, mas são compatíveis com amaioria dos bancos de dados.
Para melhor entendimento do conteúdo,subentende-se que o leitor possuaconhecimentos prévios sobre Modelagem deBancos de Dados e Teoria Relacional. Casocontrário, sugiro a leitura deste material.
2
https://www.mysql.com/http://docente.ifrn.edu.br/abrahaolopes/semestre-2013.1/3.2411.1v-prog-bd/conceitos-bd/viewhttps://www.mysql.com/
-
Vamos iniciar com uma breve introdução sobre o histórico e
características da linguagem. Apresentaremos também o modelo
de banco de dados a ser utilizado durante todo o curso.
Introdução
-
Histórico
SQL (Structured Query Language) ou Linguagem
de Consulta Estruturada é uma linguagem para
definição, acesso, manipulação e controle de Bases
de Dados Relacionais.
Baseada na Álgebra Relacional, foi desenvolvida originalmente
no início dos anos 70 nos laboratórios da IBM, dentro do projeto
System R, que tinha por objetivo demonstrar a viabilidade da
implementação do modelo relacional proposto por E. F. Codd.
A linguagem se tornou um grande padrão de banco de dados,
devido a sua eficácia, simplicidade e facilidade de uso.
4
http://pt.wikipedia.org/wiki/%C3%81lgebra_relacionalhttp://pt.wikipedia.org/wiki/Edgar_Frank_Codd
-
Características da SQL
Estilo declarativo;
Sintaxe simples e bem definida;
Pode ser utilizada interativamente ou embutida em linguagens de
programação;
Não é uma linguagem completa como C, Java ou Delphi;
Portável;
Presente nos mais importantes SGBDs Relacionais. Diferentes
fornecedores apresentam versões com algumas particularidades;
Apresenta várias padrões evolutivos: SQL86, SQL89(SQL1), SQL92
(SQL2), SQL99(SQL3). A última versão definida pela ANSI/ISO traz
características como: Stored Procedures, Triggers, Suporte à
Programação OO, XML, entre outras.
5
http://pt.wikipedia.org/wiki/Stored_procedurehttp://pt.wikipedia.org/wiki/Trigger
-
Divisões da SQL
A SQL é dividida em grupos de comandos, de acordo com a sua natureza:
DDL → Data Definition Language (Linguagem de Definição de Dados)
Reúne os comandos de criação dos objetos de Bancos;
DML → Data Manipulation Language (Linguagem de manipulação de
dados) Comandos utilizados para realizar inclusões, alterações e
exclusões dos dados;
DQL → Data Query Language (Linguagem de Consulta de Dados)
Agrupa os comandos que permitem ao usuário especificar uma consulta
DCL → Data Control Language (Linguagem de Controle de Dados).
Comandos de controle de acesso que atribuem permissões aos usuários.
DTL → Data Transaction Language (Linguagem de Transação de
Dados). Controla uma sequência de comandos e a integridade dos dados
resultantes.6
-
7
Divisões da SQL
Fonte: javatpoint.com
Obs: Esta divisão é apenas uma convenção. Alguns autores descartam a
DQL e colocam o comando SELECT como pertencendo à DML.
Em caso de concursos ou provas, verifique na bibliografia da banca, qual
a convenção utilizada.
https://www.javatpoint.com/dbms-sql-command
-
Modelo de Dados: Cadastro de Funcionários
8
Esse é o diagrama do banco de dados que
vamos criar e que usaremos em todos os
exemplos do curso.
Detalhamento nas próximas páginas...
-
Modelo de Dados: Cadastro de Funcionários
O diagrama de dados apresentado na página anterior tem finalidade
puramente didática. Não nos preocupamos com a eficiência ou correção
do modelo e sim com as possibilidades de aprendizado da SQL. Representa
uma parte do cadastro de funcionários de uma empresa fictícia:
Um funcionário pode trabalhar em um único departamento. Mas não é
obrigatório, pode ficar temporariamente sem departamento.
Um departamento pode ter vários funcionários, mas podem haver
departamentos sem funcionários.
Um funcionário pode ser alocado em vários projetos e um projeto pode
conter vários funcionários. No entanto, podem existir projetos sem
funcionários alocados e também funcionários sem projetos.
9
-
Modelo de Dados: Cadastro de Funcionários
A tabela ‘departamento’ armazena os nomes dos departamentos da
empresa que são identificados por uma chave numérica sequencial.
A tabela ‘projeto’ armazena os nomes dos projetos da empresa que são
identificados por uma sigla alfabética de três letras. O campo ‘interno’ é
uma flag booleana que indica se o projeto é interno ou não.
A tabela ‘funcionario’ armazena os dados dos funcionários que são
identificados por uma chave numérica sequencial. Possui um única
chave estrangeira ‘depto_id’ que aponta para a tabela de departamentos,
indicando qual departamento o funcionário trabalha.
A tabela ‘alocacao’ faz a associação (alocação) entre projetos e
funcionários. Dessa forma possui duas chaves estrangeiras que apontam
para as tabelas de funcionários e projetos. Armazena também as datas em
que o funcionário iniciou e saiu do projeto. Cada alocação é identificada
por uma chave numérica sequencial.10
-
A DDL reúne os comandos de definição do banco de dados e de
seus objetos, tais como criação de tabelas, índices, triggers, etc.
Neste curso cuidaremos da criação de tabelas. A criação dos
outros tipos de objetos, veremos nos outros cursos.
DDL
-
Criação do Banco de Dados
O primeiro passo para podermos testar os comandos SQL é a criação do
Banco de Dados. Fazemos isso através do comando CREATE.
Sintaxe:
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS]
nome_banco [opções]
Exemplo:
CREATE DATABASE cadastro_funcionarios
Obs:
1. DATABASE e SCHEMA são sinônimos
2. Como opção, podem ser selecionados o CHARSET e COLLATION.
Mais detalhes na outra apostila aqui.
3. IF NOT EXISTS só criará o banco se ele não existir 12
http://josecintra.com/blog/otimizacao-desempenho-bancos-dados-mysql/
-
Constraints
Na criação das tabelas, precisaremos definir os tipos de dados e
restrições (CONSTRAINTS) para os campos e tabelas.
As constraints são regras, validações impostas aos elementos
para promover a integridade dos dados. Essas restrições podem
ser definidas a nível de campo ou de tabela. Qualquer tentativa
de violação dessas regras resultará em erro e a operação não será
concretizada.13
-
Constraints
PRIMARY KEY (PK ou Chave Primária) → Especifica qual coluna
ou conjunto de colunas será a chave primária da tabela (Campo que
identifica de forma única um registro na tabela).
FOREIGN KEY (FK ou Chave Estrangeira) → Determina que uma
coluna ou conjunto de colunas é uma chave estrangeira e que, portanto,
se relaciona a uma PK de outra tabela.
UNIQUE → Determina que o valor de um campo não poderá se repetir
dentro da tabela. Será criado um índice para esse campo. Veja mais sobre
índices na outra apostila aqui.
CHECK → Especifica uma condição que a coluna precisa atender para
poder salvar o registro (a partir da versão 8 do MySQL);
NOT NULL → Determina que a coluna tem preenchimento obrigatório;
DEFAULT → Especifica um valor padrão para gravar no campo, caso
este não seja informado no comando de inserção.14
http://josecintra.com/blog/otimizacao-desempenho-bancos-dados-mysql/
-
Considerações sobre NULL e DEFAULT
O valor NULL (nulo) é especial em banco de dados e, muitas vezes difícil
de ser tratado. Ele será gravado em um campo, quando não for informado
nenhum valor para o mesmo durante a inserção (Comando INSERT).
Já, a restrição DEFAULT permite que seja definido um valor padrão para o
campo que será usado para evitar a gravação do NULL.
Dessa forma, quando não informamos um valor para o campo, na inserção,
o Banco de Dados, verificará o seguinte:
1. Caso exista um valor DEFAULT, este será gravado no campo;
2. Caso não exista o DEFAULT e o campo for NOT NULL, ocorrerá um
erro. Caso contrário será gravado o valor NULL no campo.
15
-
A chave primária (Primary Key)
Quando definimos uma chave primária, as seguintes restrições serão
impostas:
1. A tabela só pode possuir uma chave primária;
2. O campos da chave não podem conter NULL, ou seja, são obrigatórios;
3. O valor da chave será único em toda tabela, ou seja, não pode se
repetir;
4. Será criado, por padrão, um índice PRIMARY. Veja mais sobre índices
na outra apostila aqui.
5. Uma chave primária pode ser composta, ou seja, formada por mais de
um campo. Dessa forma, as regras acima valem para a combinação dos
dois campos.
Na prática, a restrição PRIMARY KEY é uma combinação de NOT
NULL e UNIQUE. 16
http://josecintra.com/blog/otimizacao-desempenho-bancos-dados-mysql/
-
Chave estrangeira e Integridade Referencial
Em um banco de dados relacional, quando um registro de uma tabela
aponta para outro em outra tabela, é necessário estabelecer regras para que
o registro "pai" não possa ser alterado ou excluído se ele tiver "filhos".
Exemplo: Na tabela departamento, não podemos excluir um
departamento se algum funcionário estiver cadastrado (trabalhando) nele.
Os tipos mais comuns de restrições de integridade são:
CASCADE → Ao se remover um registro da tabela referenciada pela
chave estrangeira, os registros relacionados àquele removido serão
eliminados em todas as tabelas relacionadas.
RESTRICT → Não permite a remoção de registros que possuam
relacionamentos em outras tabelas. (Comportamento padrão)
DEFAULT → Atribuem esses valores para as chaves estrangeiras cujos
registros relacionados foram excluídos.17
-
Tipos de Dados
O tipo de dado de uma coluna define uma faixa de valores válidos
(domínio) que podem ser armazenados nessa coluna. Define também as
operações passíveis de serem realizadas com esses valores.
O tipo de dados não é considerado uma constraint, mas possui a mesma
função, pois estabelecemos uma restrição aos valores que serão aceitos e,
caso essa regra seja violada, será emitida uma mensagem de erro.
Com certeza é mais uma forma de buscarmos garantir a integridade dos
dados.
Podemos dividir os tipos de dados do MySQL em 3 categorias:
String (Texto) → Conjunto de valores alfanuméricos (Letras, números e
caracteres especiais)
Numérico → Números inteiros e decimais de diversas precisões
Data → Data e Horários que podem ser manipulados em vários formatos18
-
Tipos de Dados Numéricos
INT, INTEGER → Inteiros regulares
BIGINT, SMALLINT e TINYINT → Inteiros grandes, pequenos e
muito pequenos
FLOAT/DOUBLE → Números de ponto flutuante de precisão simples
ou dupla
DECIMAL/NUMERIC → Números de ponto fixo que possuem melhor
precisão. Podem ser usados para valores monetários, por exemplo.
Podemos definir um tamanho para cada campo. Caso não o façamos, o
sistema assumirá o tamanho padrão.
Exemplos:
INT(5) → Define um campo inteiro com 5 dígitos
DECIMAL(8,2) → Define um número com 6 dígitos inteiros e 2 decimais 19
-
Variações dos Tipos Numéricos
Para os campos numéricos, podemos ainda definir as seguintes
propriedades:
UNSIGNED → Determina que o campo não vai aceitar valores negativos.
Útil para aumentar a faixa de valores válidos de números positivos.
AUTO_INCREMENT → O valor do campo será gerado automaticamente
de forma sequencial (1,2,3,...). Ou seja, na inclusão, o valor desse campo
não precisa ser informado, pois será atribuído o próximo da sequência.
Caso seja informado, a sequência continuará a partir desse número.
ZERO_FILL → Campos numéricos serão preenchidos com zeros à
esquerda
20
-
Tipos de Dados Texto
CHAR → Texto de comprimento fixo
VARCHAR → Texto de comprimento variável
TEXT/BLOB → Textos Grandes/Binários
VARCHAR é preferível em relação ao CHAR, pois ocupa menos espaço.
Exemplo: Seja um campo NOME definido como VARCHAR(100). Ao
armazenar o valor ‘Zé’ nesse campo, ele vai ocupar por volta de 2 bytes.
Caso o tipo do campo fosse CHAR, ocuparia por volta de 100 bytes.
No entanto, o tipo CHAR é mais rápido nas consultas.
Existem ainda os tipos NCHAR e NVARCHAR que são semelhantes, mas
aceitam valores UNICODE.
21
-
Tipos de Dados para Datas
DATE → Datas no padrão YYYY-MM-DD
DATETIME → Data e horário no padrão YYYY-MM-DD HH:MM:SS
TIME → Horário no padrão HH:MM:SS
YEAR → Um ano de 4 dígitos na faixa de 1901 até 2155.
TIMESTAMP→ Padrão UTC. Armazena os segundos desde '1970-01-01
00:00:00' UTC
Os campos DATE e DATETIME podem armazenar datas com valores entre
01/Jan/1000 até 31/Dez/9999. Já, o TIMESTAMP até ‘2038-01-09
03:14:07’.
No MySQL estão disponíveis várias funções para manipulação eformatação de datas que veremos no desenrolar do curso
22
-
Variações
GENERATED → São campos calculados a partir de outros valores e,
portanto, seus valores são gerados automaticamente no momento da
inserção/atualização do registro.
ENUM → Tipo de dados TEXTO que permite definir um conjunto de
dados discretos como domínio do campo.
Exemplo:
Podemos definir o campo SEXO como ENUM(’F’,‘M’)
O Banco de dados vai armazenar o valor 1 para masculino e 2 para
Feminino. Economiza espaço em disco, mas cuidado, pois o banco
ordena esses campos pelo seu índice.
23
-
24
Comando CREATE TABLE
Vejamos agora a sintaxe do comando CREATE TABLE usado para criar
uma nova tabela em um banco de dados:
CREATE TABLE [IF NOT EXISTS] nome_tabela
[( [nome_coluna tipo_dados [restrição_coluna]] |
[restrição_tabela],...)]
Onde: restrição_coluna e restrição_tabela são as restrições que
estudamos anteriormente.
A seguir vamos usar o comando CREATE para criar as tabelas do nosso
modelo de cadastro de funcionários e ver exemplos de cada um desses
conceitos. Antes de criarmos as tabelas, é necessário selecionar o banco de
dados com o comando USE:
USE cadastro_funcionarios
-
Criação da Tabela de Departamentos
CREATE TABLE departamento (
depto_id int unsigned NOT NULL AUTO_INCREMENT,
depto_nome varchar(45) NOT NULL,
PRIMARY KEY (depto_id)
)
Comentários:
O campo depto_id (Inteiro positivo) foi definido como chave primária
e o seu valor será incrementado automaticamente a cada inclusão (auto
incremento). Será criado um índice PRIMARY para esse campo.
O campo depto_nome não aceitará valores nulos e suportará até 45
caracteres de tamanho, mas o gerenciador armazenará somente o
tamanho ocupado.25
-
26
Criação da Tabela de Projetos
CREATE TABLE projeto (
proj_sigla char(3) NOT NULL,
proj_nome varchar(45) NOT NULL,
proj_interno tinyint DEFAULT '0',
PRIMARY KEY (proj_sigla)
)
Comentários:
O campo chave da tabela será um CHAR de 3 caracteres.
O campo proj_interno possui um valor default de ‘0’, ou seja, caso não
for informado nenhum valor na inserção, será gravado o valor ‘0’ e não
NULL.
-
Criação da Tabela de Funcionários
CREATE TABLE funcionario (
func_id int unsigned NOT NULL AUTO_INCREMENT,
func_nome varchar(100) NOT NULL,
func_nasc date NOT NULL,
func_sexo enum('F','M'),
func_salario decimal(12,2) unsigned,
depto_id int unsigned,
PRIMARY KEY (func_id),
KEY func_depto_idx (depto_id),
CONSTRAINT func_depto_fk FOREIGN KEY (depto_id)
REFERENCES departamento (`depto_id`)
)
Comentários:
O campo depto_id é uma chave estrangeira que referencia o campo depto_id da
tabela departamento e, por isso, foi criado um índice para esse campo (KEY) 27
-
28
Criação da Tabela de Alocações
CREATE TABLE alocacao (
aloca_id int unsigned NOT NULL AUTO_INCREMENT,
func_id int unsigned NOT NULL,
proj_sigla char(3) NOT NULL,
aloca_inicio datetime DEFAULT CURRENT_TIMESTAMP,
aloca_fim datetime,
PRIMARY KEY (aloca_id),
KEY aloca_proj_idx (proj_sigla),
KEY aloca_func_idx (func_id),
CONSTRAINT aloca_func_fk FOREIGN KEY (func_id)
REFERENCES funcionario (func_id),
CONSTRAINT aloca_proj_fk FOREIGN KEY (proj_sigla)
REFERENCES projeto (proj_sigla)
)
-
29
Comando ALTER TABLE
Usamos o comando ALTER TABLE para alterar a estrutura de uma tabela
existente. Podemos adicionar, alterar e excluir campos e restrições.
Sintaxe:
→ ALTER TABLE nome_tabela
ADD novas colunas | novas restrições
→ ALTER TABLE nome_tabela
CHANGE definição das colunas
→ ALTER TABLE nome_tabela
DROP coluna | restrição_coluna
-
30
Comando ALTER TABLE - Exemplos
Adicionar um novo campo à tabela funcionario:
ALTER TABLE funcionario
ADD func_comissao DECIMAL(8,4) NOT NULL;
Alterar o tamanho do campo descr_nome da tabela departamento:
ALTER TABLE departamento
CHANGE depto_nome VARCHAR(100);
Excluir da tabela funcionario o campo de comissão recém criado:
ALTER TABLE funcionario
DROP func_comissao;
-
31
Constraint CHECK
Vamos agora adicionar uma restrição CHECK para os campos de datas da
tabela de alocações. A data de início no projeto não pode ser maior que a
data da saída do projeto:
ALTER TABLE alocacao ADD CONSTRAINT data_ck
CHECK (aloca_inicio < aloca_fim)
A constraint CHECK só está disponível na versão 8.0.16 do MySQL.
-
32
Comando DROP TABLE
O comando DROP é usado para excluir um objeto do banco de dados
Sintaxe:
DROP TABLE nome_tabela
Exemplo:
DROP TABLE departamento
Obs: Este comando, assim como os demais comandos DDL, possui regras
rígidas de segurança e integridade de dados. Assim só podem ser
executados em alguns casos. Não é possível, por exemplo excluir uma
tabela que possua relacionamentos.
-
Como vimos, a DML engloba os comandos que permitem a manutenção
das informações armazenadas nas tabelas do banco de dados, ou seja,
permite realizar a inserção, alteração e exclusão de dados.
Para testar os comandos, vamos popular as tabelas criadas nos capítulos
anteriores e depois alterar e excluir alguns registros.
DML
-
34
Comando INSERT
O comando INSERT insere registros nas tabelas, atribuindo conteúdo em
seus campos de acordo com o tipo e tamanho dos dados. Dessa forma, é
necessário conhecer a estrutura da tabela que se deseja manipular.
Sintaxe:
INSERT INTO [( , ... )] VALUES
( expressão, ... );
Nome da tabela que vai receber o novo registro
Nomes dos campos que receberão os valores
Valores que serão inseridos. A expressão deve ser compatível com o campo respectivo
-
35
INSERT - Exemplos
INSERT INTO departamento
(depto_id, depto_nome)
VALUES
(1, ‘COMPRAS’)
Observações:
Neste exemplo, será inserido um novo registro na tabela departamento,
sendo que o campo depto_id receberá o valor 1 e o campo depto_nome,
o valor ‘COMPRAS’ respectivamente.
O campo depto_nome é do tipo TEXTO. Por isso, o valor inserido
deve possuir o delimitador ASPAS SIMPLES. Isso não ocorre para o
campo depto_ID, que é numérico.
Os campos e valores envolvidos devem ser compatíveis quanto ao tipo e
tamanho dos dados. Caso contrário, ocorrerá um erro.
-
36
INSERT - Exemplos
INSERT INTO departamento
(depto_nome, depto_id)
VALUES
(‘COMPRAS’, 1)
Observações:
Este exemplo é idêntico ao anterior. A ordem dos campos foi alterada,
mas a correspondência continua a mesma.
-
37
INSERT - Exemplos
INSERT INTO departamento
VALUES
(1,‘COMPRAS’)
Observações:
Este exemplo é idêntico ao anterior. Os nomes dos campos foram omitidos,
então é preciso certificar-se do seguinte:
O Sistema fará a correspondência automática entre os valores e os
campos na ordem física. Dessa forma, os valores precisam ser
compatíveis.
Todos os campos devem ser informados, exceto os não obrigatórios.
Nesse caso, utilize vírgulas adicionais
-
38
INSERT com AUTO INCREMENT
INSERT INTO departamento
(depto_nome)
VALUES
(‘COMPRAS’)
Observações:
Este exemplo é idêntico ao anterior. Só que agora usamos o recurso do
AUTO_INCREMENT.
O valor do campo depto_id (chave primária) não foi informado. Isso
causaria um erro por ser NOT NULL. No entanto, como esse campo foi
definido como “auto incrementável”, então será gravado o próximo valor
da sequência. Por exemplo, se o último valor do campo era 1, então será
gravado o valor 2 nesse campo.
-
39
INSERT - Exemplos
INSERT INTO funcionario
(func_id,func_nome,func_nasc,func_sexo,depto_id)
VALUES
(1,‘JOSÉ DA SILVA’,’2000-01-01’ ’M’,,1)
Observações:
Foi utilizado o delimitador de aspas simples para inserir a data de
nascimento. Para campos do tipo DATE, cuidado com o formato
utilizado pelo BD.
O valor do campo func_salario não foi informado. Nesse caso, será
gravado o valor NULL.
Para o campo depto_id foi informado o valor 1 que corresponde ao
departamento ‘COMPRAS’ na tabela departamento . O sistema sempre
fará a checagem da tabela relacionada, resultando em erro, caso o valor
informado não exista.
-
40
Comando UPDATE
O comando UPDATE altera os dados dos registros nas tabelas, atribuindo
o novo conteúdo em seus campos de acordo com o tipo e tamanho dos
dados. Dessa forma, é necessário conhecer a estrutura da tabela que se
deseja manipular.
Sintaxe:
UPDATE SET = , ...
[ WHERE ]
Nome da tabela cujos registros vão ser alterados
Nomes dos campos que vão ser alterados
Novos valores dos camposDetermina quais registros receberão as alterações, de acordo com a condição lógica (filtro)
-
41
UPDATE - Exemplos
UPDATE funcionário
SET func_salario = 5000.50
Este comando irá atualizar o salário de TODOS os funcionários para R$
5000,50
UPDATE funcionário
SET func_salario = func_salario * 1.10
Este comando irá atualizar o salário de TODOS os funcionários
reajustando-os em 10%.
Obs: Como não existe um filtro (WHERE) especificado a atualização será
feita em todos os registros sem distinção.
-
42
UPDATE - Exemplos
UPDATE funcionario
SET func_salario = func_salario * 1.10
WHERE depto_id = 1
Este comando irá atualizar o salário de todos os funcionários do
departamento cujo código é igual a 1, reajustando-os em 10%.
UPDATE funcionario
SET func_salario = 5000.50, depto_id = ‘M’
WHERE func_id = 1
Este comando vai atualizar o salário e o departamento ao mesmo tempo.
Vai fazer isso somente para um funcionário, pois func_id é chave primária.
-
43
Comando DELETE
O comando DELETE é simples e direto. Sua função é excluir registros da
tabela de acordo com uma condição especificada.
Sintaxe:
DELETE FROM [WHERE ]
Tabela da qual queremos excluir os registros
Filtro (condição) especificando quais registros vão ser excluídos
-
44
DELETE - Exemplos
→DELETE FROM projetos
→DELETE FROM projetos where proj_sigla = ‘XYZ’
Observações:
O primeiro exemplo exclui incondicionalmente todos os registros da
tabela de projetos.
O segundo exemplo excluir apenas o projeto de sigla = 1 (primary
key).
O sistema irá verificar se existe algum funcionário relacionado ao projeto
na tabela alocacao, caso exista, ocorrerá um erro, a menos que o
relacionamento tenha sido feito com a opção CASCADE. Isso vale
também para o comando UPDATE.
-
A DQL engloba os comandos que permitem a realização de consultas à
base de Dados. Ou seja, o SELECT!
Com o comando SELECT é possível pesquisar dados em uma ou mais
tabelas de acordo com o critério de filtro definido. É o astro da SQL e o
mais complexo comando da linguagem, como veremos a seguir...
DQL
-
46
SELECT – Dados de Trabalho
Tabela funcionario Tabela departamento
Tabela projeto Tabela alocação
Essas são as tabelas já preenchidas com os dados que vamos utilizar nos
exemplos com SELECT. Todos os nomes e valores são fictícios. Veja que a
funcionária “Maria de Souza” ainda não tem um departamento e o
departamento de “contabilidade” está sem funcionários.
func_id func_nome func_nasc func_sexo func_salario depto_id
1 JOSÉ DA SILVA 2000-01-01 M 5000 1
2 MARIA DA SILVA 1987-02-01 F 8000,5 1
3 JOÃO DA SILVA 1970-01-01 M 5500,5 2
4 ANTONIO ALCÂNTARA 2000-03-01 M 6500 2
5 MARIA DE SOUZA 1990-05-01 F 6500 NULL
6 LUIZ MOURA 1960-05-01 M 7500 4
7 JOANA OLIVEIRA 1975-02-01 F 9000,7 1
depto_id depto_nome
1 COMPRAS
2 VENDAS
3 CONTABILIDADE
4 INFORMÁTICA
proj_sigla proj_nome proj_interno
123 Projeto 123 0
ABC Projeto ABC 0
PQR Projeto PQR 1
XYZ Projeto XYZ 0
aloca_id func_id proj_sigla aloca_inicio aloca_fim
1 1 XYZ 2019-01-01 00:00:00
2 1 123 2020-01-01 00:00:00
3 2 XYZ 2019-01-01 00:00:00 2020-01-01 00:00:00
4 3 PQR 2018-01-01 00:00:00
5 4 123 2019-01-01 00:00:00
-
47
Comando SELECT
Sintaxe:
SELECT [ ALL | DISTINCT ]
FROM
[ WHERE ]
[ GROUP BY , ...
[ HAVING ] ]
ORDER BY [ ASC | DESC ], ...]
A cláusula FROM indica em qual tabela, view ou query vai ser realizada
a consulta.
A lista de atributos contém a relação de campos que vão ser
requisitados na consulta.
A cláusula WHERE determina o filtro da pesquisa com os parâmetros e
critérios de busca.
Detalharemos essas e as demais opções a seguir...
-
48
SELECT – Lista de Campos
A lista de campos do comando SELECT indica quais colunas ou
expressões vão ser mostrados no resultado da consulta. Para exibir todos as
colunas, use o caractere *.
É possível mudar os nomes dos campos para exibição, atribuindo-lhes um
apelido (alias). Da mesma forma, podemos colocar um prefixo para o
campo, indicando sua tabela de origem:
[nome_da_tabela].nome_do_campo | expressão [AS]
[apelido_do_campo]
Como exemplo, o campo nome_func da tabela funcionario pode ser
indicado por uma das quatro formas, entre outras:
func_nome ♦ funcionario.func_nome
func_nome AS nome ♦ funcionario.func_nome AS nome
-
49
SELEC T – Lista de Campos
Os seguintes comandos são equivalentes e listam todos os campos da tabela
funcionario:
SELECT
func_id,func_nome,func_nasc,func_sexo,func_salario,depto_id
FROM funcionário
SELECT * FROM funcionario
Obs: Como não foi usada a cláusula WHERE, serão exibidos todos os
registros também:
func_id func_nome func_nasc func_sexo func_salario depto_id
1 JOSÉ DA SILVA 2000-01-01 M 5000.00 1
2 MARIA DA SILVA 1987-02-01 F 8000.50 1
3 JOÃO DA SILVA 1970-01-01 M 5500.50 2
4 ANTONIO ALCÂNTARA 2000-03-01 M 6500.00 2
5 MARIA DE SOUZA 1990-05-01 F 6500.00 NULL
6 LUIZ MOURA 1960-05-01 M 7500.00 4
7 JOANA OLIVEIRA 1975-02-01 F 9000.70 1
-
50
SELECT – Lista de Campos
Neste exemplo selecionamos 3 campos e um campo calculado da tabela
funcionario, usando aliases:
SELECT
funcionario.func_id AS Código,
func_nome Nome,
func_salario Salário,
(func_salario*1.10) AS ’Salário Reajustado’ FROM funcionario
Apelidos
Campo Calculado
Prefixo (opcional nesse caso)
Código Nome Salário Salário Reajustado
1 JOSE DA SILVA 5000.00 5500.00
2 MARIA DA SILVA 8000.50 8800.55
3 JOÃO DA SILVA 5500.50 6050.55
4 ANTONIO ALCÂNTARA 6500.00 7150.00
5 MARIA DE SOUZA 6500.00 7150.00
6 LUIZ MOURA 7500.00 8250.00
7 JOANA OLIVEIRA 9000.70 9900.77
-
51
SELECT – Cláusula ORDER BY
Podemos ordenar os resultados de uma consulta através da cláusula
ORDER BY.
Sintaxe:
ORDER BY {|expressão [ ASC | DESC]}
Observações
atributo: Campo ou expressão que vai ser utilizado como critério para a
ordenação. Podemos usar mais de um campo.
ASC: Ordenação ascendente (crescente)
DESC: Ordenação descendente (decrescente)
Caso o sentido da ordenação não seja informado, o padrão será ASC;
A cláusula ORDER BY deve vir depois da cláusula WHERE, caso esta
exista.
-
SELECT * FROM funcionario ORDER BY func_nome
Este exemplo irá listar os funcionários em ordem crescente de nome
(campo func_nome):
52
SELECT – Cláusula ORDER BY
func_id func_nome func_nasc func_sexo func_salario depto_id
4 ANTONIO ALCÂNTARA 2000-03-01 M 6500.00 2
7 JOANA OLIVEIRA 1975-02-01 F 9000.70 1
3 JOÃO DA SILVA 1970-01-01 M 5500.50 2
1 JOSÉ DA SILVA 2000-01-01 M 5000.00 1
5 MARIA DE SOUZA 1990-05-01 F 6500.00 NULL
6 LUIZ MOURA 1960-05-01 M 7500.00 4
2 MARIA DA SILVA 1987-02-01 F 8000.50 1
-
53
SELECT – Cláusula ORDER BY
select * from funcionario order by depto_id ASC,
func_salario DESC
Este exemplo irá listar os funcionários em ordem crescente de
departamento (campo depto_id) e, dentro de departamento, em ordemdecrescente de salário (campo func_salario):
func_id func_nome func_nasc func_sexo func_salario depto_id
5 MARIA DE SOUZA 1990-05-01 F 6500.00 NULL
7 JOANA OLIVEIRA 1975-02-01 F 9000.70 1
2 MARIA DA SILVA 1987-02-01 F 8000.50 1
1 JOSÉ DA SILVA 2000-01-01 M 5000.00 1
3 JOÃO DA SILVA 1970-01-01 M 6500.00 2
4 ANTONIO ALCÂNTARA 2000-03-01 M 5500.50 2
6 LUIZ MOURA 1960-05-01 M 7500.00 4
-
A cláusula WHERE permite filtar os registros a serem exibidos de acordocom uma condição do pesquisa que é basicamente uma coleção depredicados que podem ser combinados através dos operadores booleanosAND, OR, NOT.
Um predicado pode ser:
• Uma comparação com os operadores condicionais (=,,=,)
• Um predicado de BETWEEN para pesquisa em faixas de valores
• Um predicado IN para buscar um valor em um conjunto
• Um predicado de LIKE para busca de trechos em campos texto
• Um teste de valor nulo
Vejamos cada um deles…
SELECT – Cláusula WHERE
54
-
Fumncionários que trabalham no departamento de número 2:
SELECT * FROM funcionario WHERE depto_id = 2
Funcionários que NÃO trabalham no departamento de número 2:
SELECT * FROM funcionario WHERE depto_id 2
Veja que a consulta não trouxe códigos de departamentos nulos. Veremosmais à frente como tratar campos nulos.
SELECT – Comparações
func_id func_nome func_nasc func_sexo func_salario depto_id
3 JOÃO DA SILVA 1970-01-01 M 5500.50 2
4 ANTONIO ALCÂNTARA 2000-03-01 M 6500.00 2
func_id func_nome func_nasc func_sexo func_salario depto_id
1 JOSÉ DA SILVA 2000-01-01 M 5000.00 1
2 MARIA DA SILVA 1987-02-01 F 8000.50 1
7 JOANA OLIVEIRA 1975-02-01 F 9000.70 1
6 LUIZ MOURA 1960-05-01 M 7500.00 4
55
-
Funcionários que recebem salário maior que R$ 7.000,00:
SELECT * FROM funcionario WHERE func_salario > 7000
Funcionários que trabalham no departamento de número 1 e recebemsalário maior que R$ 7.000,00:
SELECT * FROM funcionario WHERE depto_id = 1 AND
func_salario > 7000
SELECT – Comparações
func_id func_nome func_nasc func_sexo func_salario depto_id
2MARIA DA SILVA 1987-02-01 F 8000,5 1
6LUIZ MOURA 1960-05-01 M 7500 4
7JOANA OLIVEIRA 1975-02-01 F 9000,7 1
func_id func_nome func_nasc func_sexo func_salario depto_id
2 MARIA DA SILVA 1987-02-01 F 8000,5 1
7 JOANA OLIVEIRA 1975-02-01 F 9000,7 156
-
Funcionários Homens que recebem salários maiores que R$ 6.000,00 eMulheres que ganham salários menores que R$ 7.000,00 :
SELECT * FROM funcionario WHERE
(func_sexo = ‘M’AND func_salario > 6000) OR
(func_sexo = ‘F’AND func_salario < 7000)
SELECT – Comparações
func_id func_nome func_nasc func_sexo func_salario depto_id
4ANTONIO ALCÂNTARA 2000-03-01 M 6500 2
5MARIA DE SOUZA 1990-05-01 F 6500 NULL
6LUIZ MOURA 1960-05-01 M 7500 4
57
-
A cláusula BETWEEN é usada para facilitar a filtragem de faixas devalores.
Exemplo: Listar os funcionários que recebem salários entre R$ 6.000,00 eR$ 8.000,00 (inclusive)
Uma solução usando operadores condicionais poderia ser:
SELECT * FROM funcionario
WHERE func_salario >= 6000 AND
func_salario
-
A cláusula IN é usada para facilitar a realização de comparações múltiplas
Exemplo: Listar os funcionários que trabalham nos departamentos 1, 3 e 5
Uma solução usando operadores condicionais poderia ser:
SELECT * FROM funcionario WHERE
depto_id = 1 OR depto_id = 3 OR depto_id = 5
Usando a cláusula IN fica:
SELECT * FROM funcionario
WHERE depto_id IN (1,3,5)
Obs: Caso os valores sejam do tipo texto, colocá-los entre aspas simples.
Mais para frente, falaremos sobre IN em subconsultas.
SELECT – Cláusula IN
59
-
O operador LIKE é usada para localizar trechos de textos em camposalfanuméricos de acordo com padrões. Para isso são usados os caracterescoringa (wildcards) que são os seguintes:
Qualquer nome que termine em ‘SILVA’:
SELECT * FROM funcionario WHERE func_nome LIKE ‘%SILVA’
Qualquer nome que comece com ‘MARIA’:
SELECT * FROM funcionario WHERE func_nome LIKE ‘MARIA%’
Qualquer nome que termine em ‘S’ seguido de 3 letras e depois a letra ‘A’:
SELECT * FROM funcionario WHERE func_nome LIKE '%S___A’
Nesse último exemplo vai trazer os sobrenomes SILVA e SOUZA.
SELECT – LIKE
WildCard Função
% Qualquer quantidade de caracteres
_ Exatamente um caractere
60
-
Os valores nulos são um caso à parte e são muito difíceis de seremtrabalhados pelos seguintes motivos:
• Um valor nulo nunca é igual à outro;
• Operações com nulos sempre retornam nulos, sejam eles numéricos ounão.
Desta forma, por exemplo:
10 * NULL = NULL;
10 + NULL = NULL;
Para trabalhar com valores nulos temos, entre outros, os seguintesoperadores e funções:
IS NULL / IS NOT NULL→ Comparam valores com NULL
COALESCE() → Função que substitui um valor nulo por outro não nulo.
Existe também a função IFNULL que produz o mesmo resultado.
SELECT –Valores nulos (NULL)
61
-
Exemplo 1: Pesquisar os funcionários que não estão cadastrados emnenhum departamento (cod_depto é nulo):
SELECT * FROM funcionario WHERE depto_id IS NULL
Exemplo 2: Pesquisar os funcionários que estão alocados em algumdepartamento:
SELECT * FROM funcionario WHERE depto_id IS NOT NULL
Exemplo 3: Mostrar os salários acrescidos de 1000, mesmo para saláriosnulos:
SELECT COALESCE(func_salario,0) + 1000 FROM funcionario
Obs: Neste ultimo caso, os salários nulos serão convertidos para 0(ZERO) antes de serem somados. Caso contrário, o resultado da soma seriaNULL.
SELECT –Tratando Valores Nulos
62
-
SQL não é sensível ao caso, portanto escrever SELECT ou select ouSeLeCt é a mesma coisa. No entanto, o mesmo não vale para o conteúdodos campos que nem sempre é sensível ao caso. Isso depende doCHARSET e COLLATION usados. Dessa forma, ‘ANTONIO’ pode serdiferente de ‘antonio’.
Para fazer pesquisas não sensíveis ao caso, usamos as seguintes funções:
UPPER() → Converte as letras para maiúscula
LOWER() → Converte as letras para minúsculas
Exemplos: Os seguintes comando produzem o mesmo resultado:
• SELECT * FROM funcionario WHERE
UPPER(func_nome) = ‘JOSE DA SILVA’
• SELECT * FROM funcionario WHERE
LOWER(func_nome) = ‘jose da silva’
SELECT – Maiúsculas e Minúsculas
63
-
64
SELECT – Cláusula DISTINCT
A cláusula DISTINCT é usada para eliminar do resultado da consulta todas
as linhas duplicadas.
Exemplo: Como listar todos os números de departamentos que
possuem funcionários alocados?
Precisamos fazer um SELECT na tabela funcionario trazendo os
departamentos, pois assim garantimos que um funcionário está alocado no
departamento. Uma solução poderia ser o seguinte comando:
SELECT depto_id FROM funcionario
No entanto, esse comando trará vários departamentos repetidos. Para
resolver, usamos a cláusula DISTINCT da seguinte forma:
SELECT DISTINCT depto_id FROM funcionario
Obs: A cláusula DISTINCT deve vir logo após o comando SELECT e se
aplica a todas as colunas selecionadas.
-
65
SELECT – Cláusula LIMIT
A cláusula LIMIT é usada para limitar o número de registros retornados. É
útil para fazer relatórios paginados ou para testes em tabelas grandes, além
de outras finalidades.
Exemplo1: Busca os três primeiros funcionários:
select * from funcionario limit 3
Exemplo2: Busca os três primeiros funcionários a partir do segundo
registro:
select * from funcionario limit 2,3
-
66
SELECT – CASE
A expressão CASE é uma estrutura de controle que permite adicionar lógica
if-else a uma consulta SELECT. Ela permite escolher um valor entre um
conjunto de valores.
CASE value
WHEN value1 THEN result1
WHEN value2 THEN result2
…
[ELSE else_result]
END
Exemplo: Exibindo o sexo por extenso.
SELECT func_nome,
CASE func_sexo
WHEN 'F' THEN 'feminino’
ELSE 'Masculino’
END AS Sexo
FROM funcionario
Obs:
É possível também usar expressões
lógicas para os valores
-
67
SELECT – Funções de Agregação
As funções de agregação permitem a execução de operações matemáticas e
estatísticas sobre um conjunto de dados, retornando um único valor
totalizador.
As principais funções de agregação em MySQL são:
MIN → Valor Mínimo
MAX → Valor Máximo
AVG → Média Aritmética
SUM → Soma
COUNT → Contagem
As funções de agregação recebem como parâmetro o nome do campo que
vai ser totalizado e, com algumas exceções, desconsideram na totalização os
valores NULL.
-
68
SELECT – Funções de Agregação – Exemplos
Contar o número total de registros da tabela de departamentos:
select count(depto_id) from departamento
Calcular a média de salários dos funcionários:
select avg(func_salario) from funcionário
Calcular a média de salários dos funcionários do departamento 1:
select avg(func_salario) from funcionario
where depto_id = 1
Calcular a soma de salários e o menor salário do departamento 1
select sum(func_salario), min(func_salario)
from funcionario where depto_id = 1
Use DISTINCT para ignorar valores duplicados na agregação:
select avg(DISTINCT func_salario) from funcionário
-
69
SELECT – Cláusula GROUP BY
Usamos a cláusula GROUP BY para agrupar registros em subgrupos
baseados em valores retornados por um campo ou expressão. É usado
frequentemente em conjunto com funções de agregação para produzir
subtotais.
Exemplo: Obter a média dos salários para cada departamento:
SELECT depto_id, AVG(func_salario) AS 'Média’
FROM funcionario GROUP BY depto_id
depto_id MédiaNULL 6500
1 7333,7333332 6000,254 7500
-
70
SELECT – Cláusula GROUP BY - Exemplos
Exemplo 1: Obter a média dos salários para cada departamento:
SELECT depto_id, AVG(func_salario) AS 'Média’
FROM funcionario GROUP BY depto_id
Exemplo 1: Obter a média dos salários por sexo e departamento:
SELECT depto_id, func_sexo, AVG(func_salario) AS 'Média’
FROM funcionario GROUP BY depto_id,func_sexo
depto_id MédiaNULL 6500
1 7333,733333
2 6000,254 7500
depto_id func_sexo Média
1M 50001F 8500,62M 6000,25
NULLF 6500
4M 7500
-
71
SELECT – Cláusula GROUP BY & HAVING
Muitas vezes é necessário filtrar os dados dos agrupamentos retornados pelo
GROUP BY. Para isso, empregamos a cláusula HAVING que permite
especificar condições para inclusão dos grupos nas agregações. É
semelhante à cláusula WHERE, mas não se aplica aos registros e sim aos
agrupamentos do GROUP BY,
Exemplo: Somar os salários agrupados por departamento e sexo, mas
excluir as somas menores ou iguais a 5000,00:
SELECT depto_id, func_sexo, SUM(func_salario) AS 'Soma’
FROM funcionario GROUP BY depto_id,func_sexo
HAVING SUM(func_salario) > 5000
depto_id func_sexo Soma
1F 17001,22M 12000,5
NULLF 65004M 7500
-
72
SELECT – Subconsultas
Uma subconsulta, na prática, é uma instrução SELECT dentro de outra
instrução SQL.
Podemos embutir uma instrução SELECT em vários pontos de outra
instrução SELECT:
• Como uma nova coluna da consulta. O campo é um SELECT.
• Como filtro de uma consulta (cláusula WHERE).
• Como fonte de dados de outra consulta (cláusula FROM).
A seguir, vamos fazer alguns exemplos para demonstrar esse recurso.
-
Exemplo: Trazer a quantidade de funcionários que trabalham em cada
departamento:
SELECT
d.depto_id,
d.depto_nome,
(SELECT COUNT(*) FROM funcionario AS f
WHERE f.depto_id = d.depto_id) AS ‘Qtde’
FROM
departamento AS d
73
SELECT – Subconsulta Como Campo
Essa subconsulta destacada em verde é um campo da consulta
principal e recebe um nome (alias) de ‘Qtde’.
Em sua cláusula WHERE, ela faz referência a um campo
da consulta principal. Veja que os parênteses são importantes
depto_id depto_nome Qtde
1COMPRAS 3
2VENDAS 2
3CONTABILIDADE 0
4INFORMÁTICA 1
-
Exemplo: Usar a consulta do exemplo 1 (página anterior) para trazer os
departamentos que não possuem funcionários:
SELECT * FROM (
SELECT
d.depto_id,
d.depto_nome,
(SELECT COUNT(*) FROM funcionario AS f
WHERE f.depto_id = d.depto_id) AS ‘Qtde’
FROM
departamento AS d
) AS tabela WHERE t.qtde = 0
74
SELECT – Subconsulta Como Fonte de Dados
Essa subconsulta destacada em verde é agora usada na
cláusula FROM como se fosse uma tabela ou view.
Seus campos podem ser referenciados normalmente na
consulta principal através do seu alias (tabela)
depto_id depto_nome Qtde
3CONTABILIDADE 0
-
Exemplo: Trazer os códigos e nomes dos funcionários que já trabalharam
em pelo menos um projeto:
SELECT
f.func_id,f.func_nome
FROM
funcionario f
WHERE
f.func_id IN (SELECT DISTINCT a.func_id FROM alocacao a)
75
SELECT – Subconsulta Como Filtro
Essa subconsulta destacada em verde é agora usada
na cláusula WHERE através do operador IN
func_id func_nome
1JOSÉ DA SILVA
2MARIA DA SILVA
3JOÃO DA SILVA
4ANTONIO ALCÂNTARA
-
Os bancos de dados relacionais como o MySQL armazenam as informações
em tabelas separadas mas relacionadas entre si através de campos comuns.
Esses campos comuns são as chaves primárias e estrangeiras que permitem
juntar as informações para produzir um resultado só. O comando SELECT
disponibiliza algumas cláusulas que permitem efetuar junções entre tabelas,
mesmo sem haver campos comuns.
Você vai ver nos exemplos que, quando trabalhamos com junções de
tabelas, é muito comum atribuirmos apelidos para as tabelas para evitar
conflitos entre nomes de campos iguais e também para simplificar a escrita
76
SELECT – Junções de Tabelas
-
CROSS JOIN → Retorna a combinação de todos os registros das duas
tabelas sem nenhum critério. Na verdade, é um PRODUTO
CARTESIANO e não será abordado nesse curso.
INNER JOIN → Retorna somente registros que possuem valores
correspondentes nas duas tabelas de acordo com o critério de junção.
OUTER JOIN → Retorna registros das duas tabelas de acordo com o
seguinte:
LEFT JOIN → Todos os Registros da tabela à esquerda e os registros
correspondentes da tabela direita
RIGHT JOIN → Todos os Registros da tabela à direita e os registros
correspondentes da tabela esquerda
FULL JOIN → Todos os registros, quando houver uma
correspondência, e os não correspondentes das tabelas esquerda e
direita. Obs: O MySQL não suporta FULL JOINS.77
SELECT – Junções de Tabelas
-
78
SELECT – Junções de Tabelas
Fonte: terminalroot.com.br
https://terminalroot.com.br/2019/10/inner-join-left-join-right-join-mysql.html
-
Para exemplificar melhor essas formas de junção, veremos um estudo de
caso.
Vamos supor que o seu chefe imediato te pediu um relatório simples com
todos os códigos e nomes dos funcionários e os nomes de seus
respectivos departamentos.
Como o nome e o código do funcionários estão na tabela funcionario, mas
o nome do departamento está na tabela departamento, a primeira ideia que
você teve foi juntar as duas tabelas usando o campo comum depto_id,
através de um INNER JOIN.
→79
SELECT – Junções de Tabelas - Exemplos
-
SELECT
f.func_id,f.func_nome,d.depto_nome
FROM
funcionario f
INNER JOIN
departamento d
ON
f.depto_id = d.depto_id
80
SELECT – Junções de Tabelas – INNER JOIN
func_id func_nome depto_nome
1JOSÉ DA SILVA COMPRAS
2MARIA DA SILVA COMPRAS
7JOANA OLIVEIRA COMPRAS
3JOÃO DA SILVA VENDAS
4ANTONIO ALCÂNTARA VENDAS
6LUIZ MOURA INFORMÁTICA
Destacado em verde, vemos a junção por
igualdade do campo ‘depto_id’ presente
nas duas tabelas.
Veja que o registro 5 não apareceu, pois
está com NULL nesse campo
O seu chefe não gostou desse relatório!
Não apareceu a MARIA DE SOUZA.
A solução é refazer usando LEFT
JOIN, que veremos a seguir →
-
SELECT
f.func_id,f.func_nome,d.depto_nome
FROM
funcionario f
LEFT JOIN
departamento d
ON
f.depto_id = d.depto_id
81
SELECT – Junções de Tabelas – LEFT JOIN
Destacado em verde, vemos a junção por
igualdade com LEFT JOIN.
Agora apareceu o registro cinco
O seu chefe AINDA não gostou desse
relatório:
Cadê o departamento de
contabilidade?
A solução é refazer usando RIGHT
JOIN, que veremos a seguir →
func_id func_nome depto_nome
1JOSÉ DA SILVA COMPRAS
2MARIA DA SILVA COMPRAS
3JOÃO DA SILVA VENDAS
4ANTONIO ALCÂNTARA VENDAS
5MARIA DE SOUZA NULL
6LUIZ MOURA INFORMÁTICA
7JOANA OLIVEIRA COMPRAS
-
SELECT
f.func_id,f.func_nome,d.depto_nome
FROM
funcionario f
RIGHT JOIN
departamento d
ON
f.depto_id = d.depto_id
82
SELECT – Junções de Tabelas – RIGHT JOIN
Destacado em verde, vemos a junção por
igualdade com RIGHT JOIN.
Agora apareceu o departamento de
CONTABILIDADE, mas o registro 5
Desapareceu de novo
É melhor nem levar esse relatório para
o seu chefe:
A contabilidade está ok, mas a MARIA
DE SOUZA desapareceu!
A solução é refazer usando UNION,
que veremos a seguir →
func_id func_nome depto_nome
1JOSÉ DA SILVA COMPRAS
2MARIA DA SILVA COMPRAS
3JOÃO DA SILVA VENDAS
4ANTONIO ALCÂNTARA VENDAS
5MARIA DE SOUZA NULL
6LUIZ MOURA INFORMÁTICA
7JOANA OLIVEIRA COMPRAS
-
Pois é, você ia finalizar o relatório usando FULL OUTER JOIN para
resolver o problema, mas eis que você descobre que o MYSQL não o
suporta.
A solução é fazer uma gambi com UNION.
A cláusula UNION combina duas ou mais declarações SELECT. O
resultado de cada SELECT deve possuir o mesmo número de colunas, e o
tipo de dado de cada coluna correspondente deve ser compatível. O nome
das colunas não precisam ser iguais.
Dessa forma, podemos combinar duas consultas, uma com LEFT JOIN e
outra com RIGHT JOIN para produzir o mesmo resultado de uma consulta
com FULL OUTER JOIN.
Obs: Por padrão, o operador UNION elimina resultados duplicados. Para
incluí-los, acrescente a palavra ALL.
→ 83
SELECT – Junções de Tabelas – FULL JOIN
-
SELECT
f.func_id,f.func_nome,d.depto_nome
FROM
funcionario f
LEFT JOIN
departamento d
ON
f.depto_id = d.depto_id
UNION
SELECT
f.func_id,f.func_nome,d.depto_nome
FROM
funcionario f
RIGHT JOIN
departamento d
ON
f.depto_id = d.depto_id
84
SELECT – Junções de Tabelas – UNION
Pronto. Com o uso de UNION
Conseguimos o resultado
esperado. O seu chefe te elogiou,
mas pediu uma última alteração:
Mudar o valor NULL para uma
coisa mais bonitinha
Ainda bem que aprendemos a
função COALESCE. Vejamos a
versão final do relatório →
func_id func_nome depto_nome
1 JOSÉ DA SILVA COMPRAS
2 MARIA DA SILVA COMPRAS
3 JOÃO DA SILVA VENDAS
4 ANTONIO ALCÂNTARA VENDAS
5 MARIA DE SOUZA NULL
6 LUIZ MOURA INFORMÁTICA
7 JOANA OLIVEIRA COMPRAS
NULL NULL CONTABILIDADE
-
Algumas funções do MYSQL que podemos usar para facilitar as consultas:
• CURDATE→ Retorna da data corrente
• YEAR(), MONTH() e DAY() → Extraem o ano, o mês e o dia de uma data passadacomo parâmetro
Ex: MONTH(‘2019-01-01’) # Retorna: 1
• DATEDIFF()→ Retorna o número de dias entre duas datasEx: DATEDIFF(‘2020-06-25’, ‘2020-06-15’) # Retorna: 10
• TIMESTAMPDIFF() → Retorna a diferença entre duas datas em uma unidadeespecífica (anos, meses, segundos, etc.)
Ex: TIMESTAMPDIFF(DAY,'2022-02-01','2022-02-21’) # Retorna: 10
• DATE_FORMAT()→ Formata uma data de acordo com os parâmetrosEx: DATE_FORMAT("2020-06-15", "%d/%m/%Y") # Retorna:15/06/2020
85
SELECT – Funções com DatasTIMESTAMPDIFF(DAY,'2022-02-01','2022-02-21')
TIMESTAMPDIFF(DAY,'2022-02-01','2022-02-21')
-
A seguir alguns exercícios resolvidos com o comando SELECT ...
Exercícios
-
1) Listar o menor e o maior salário agrupados por departamento
SELECT
d.depto_nome AS Departamento,
MIN(f.func_salario) AS 'Menor Salário',
MAX(f.func_salario) AS 'Maior Salário'
FROM
funcionario f
INNER JOIN
departamento d ON f.depto_id = d.depto_id
GROUP BY
d.depto_nome
87
Exercícios Resolvidos
-
2) Listar Código, nome do funcionário, seu departamento e em quantos
projetos ele trabalhou
SELECT
f.func_id AS Código,
f.func_nome AS Nome,
IFNULL(d.depto_nome,'N/C') AS Departamento,
(SELECT count(a.aloca_id) from alocacao a where a.func_id = f.func_id)
AS Projetos
FROM
funcionario f
LEFT JOIN
departamento d ON f.depto_id = d.depto_id
88
Exercícios Resolvidos
-
3) Listar Código e nome dos funcionários que recebem salário maior do que
a média de salários da empresa:SELECT
f.func_id AS Código,
f.func_nome AS Nome,
f.func_salario As Salário
FROM
funcionario f
WHERE
f.func_salario >=
(SELECT AVG(func_salario) FROM funcionario)
Veja que essa consulta não é muito “performática” se não existirem índices
para o campo de salário. O plano de execução do MySQL é inteligente, mas
o ideal, nesse caso, é criar um script onde a média dos salários é calculada
para uma variável e depois comparar os salários com essa variável.
Veremos sobre criação de scripts SQL em outro curso. 89
Exercícios Resolvidos
-
4) Listar nome, data de Nascimento e a idade dos funcionários que fazem
aniversário neste mês (mês atual)
SELECT
f.func_nome as Nome,
f.func_nasc AS Nascimento,
TIMESTAMPDIFF(YEAR,f.func_nasc,CURDATE()) AS Idade
FROM
funcionario f
WHERE
MONTH(curdate()) = (MONTH(f.func_nasc))
90
Exercícios Resolvidos
-
5) Listar a quantidades de projetos NÃO internos iniciados em cada ano
SELECT
YEAR(a.aloca_inicio) AS Ano,
count(p.proj_sigla) As 'Qtde.Projetos'
FROM
projeto p
INNER JOIN
alocacao a
ON
p.proj_sigla = a.proj_sigla
WHERE
NOT p.proj_interno
GROUP BY
YEAR(a.aloca_inicio)
91
Exercícios Resolvidos
-
6) Emitir uma listagem geral dos funcionários, seus departamentos e
projetos, incluindo os que não trabalharam em projetos e não estão em
nenhum departamento.
SELECT
f.func_id,
f.func_nome,
IFNULL(d.depto_nome,'N/C’),
IFNULL(p.proj_nome,'N/C')
FROM
funcionario f
LEFT JOIN
departamento d ON f.depto_id = d.depto_id
LEFT JOIN
alocacao a ON a.func_id = f.func_id
LEFT JOIN
projeto p ON p.proj_sigla = a.proj_sigla 92
Exercícios Resolvidos
-
FIMObrigado!
93
-
94
Referências
Links
https://dev.mysql.com/doc/
https://www.tutorialspoint.com/sql/index.htm
https://www.w3schools.com/sql/
http://www.bosontreinamentos.com.br/curso-completo-de-mysql/
http://www.josecintra.com/blog
Livros
Lynn Beighley - Use a Cabeça SQL – Alta Books
C.J.Date - SQL e Teoria Relacional - Editora Novatec
https://dev.mysql.com/doc/http://www.inf.pucrs.br/~danielc/bda/SQL1.ppthttps://www.w3schools.com/sql/http://www.josecintra.com/bloghttp://www.josecintra.com/blog