Funções Avançadas
Funções Avançadas
🌍 Analogia do Mundo Real
SQL é como um canivete suíço — além da "lâmina" (consultas) e da "serra" (agregação) que você já aprendeu, ele tem muitas outras ferramentas úteis:
- Funções de string = Editor de texto — concatenar, extrair, conversão de maiúsculas/minúsculas
- Funções numéricas = Calculadora — arredondamento, piso, valores absolutos
- Funções de data = Calendário — obter data atual, calcular diferenças de dias, extrair ano/mês/dia
- Conversão de tipo = Tradutor — converter entre números, texto e datas
Dominar essas funções permite que você faça mais processamento de dados no SQL, reduzindo a necessidade de processamento adicional na camada de aplicação.
🎯 Conceitos Fundamentais
Funções de String
CONCAT — Concatenação de Strings
Junta múltiplas strings em uma só.
-- Concatenar nome
SELECT CONCAT(first_name, ' ', last_name) AS nome_completo
FROM employees;
-- MySQL também suporta || para concatenação (requer PIPES_AS_CONCAT habilitado)
-- SELECT first_name || ' ' || last_name FROM employees;
SUBSTRING — Extrair Substring
Extrai uma parte de uma string.
-- Extrair a parte do nome de usuário de um e-mail (antes do @)
SELECT email, SUBSTRING(email, 1, POSITION('@' IN email) - 1) AS nome_usuario
FROM employees
WHERE email IS NOT NULL;
-- Extração simples: começar da posição 1, pegar 3 caracteres
SELECT SUBSTRING('Hello World', 1, 3); -- Resultado: Hel
UPPER / LOWER — Conversão de Maiúsculas/Minúsculas
SELECT UPPER('hello') AS maiusculo, LOWER('WORLD') AS minusculo;
-- Resultado: HELLO, world
-- Uso prático: busca sem diferenciar maiúsculas de minúsculas
SELECT * FROM employees WHERE LOWER(email) = 'zhangsan@company.com';
TRIM — Remover Espaços
-- Remover espaços do início e do fim
SELECT TRIM(' hello ') AS sem_espacos; -- Resultado: hello
-- Remover caracteres especificados
SELECT TRIM(LEADING '0' FROM '0012300'); -- Resultado: 12300
REPLACE — Substituir String
-- Mascarar os 4 dígitos do meio de um número de telefone com ****
SELECT phone, REPLACE(phone, SUBSTRING(phone, 4, 4), '****') AS mascarado
FROM employees;
LENGTH — Comprimento da String
SELECT first_name, LENGTH(first_name) AS comprimento_nome
FROM employees;
Funções Numéricas
ROUND — Arredondamento
SELECT ROUND(3.14159, 2); -- Resultado: 3.14
SELECT ROUND(3.14159, 0); -- Resultado: 3
SELECT ROUND(1234.5, -2); -- Resultado: 1200 (arredondar para centenas)
CEIL / FLOOR — Arredondar para Cima / para Baixo
SELECT CEIL(3.1); -- Resultado: 4 (arredondar para cima)
SELECT CEIL(3.0); -- Resultado: 3
SELECT FLOOR(3.9); -- Resultado: 3 (arredondar para baixo)
SELECT FLOOR(3.0); -- Resultado: 3
CEILING(), Oracle usa CEIL().
ABS — Valor Absoluto
SELECT ABS(-100); -- Resultado: 100
SELECT ABS(50); -- Resultado: 50
MOD — Módulo (Resto)
SELECT MOD(10, 3); -- Resultado: 1
SELECT MOD(100, 7); -- Resultado: 2
-- SQL Server não suporta a função MOD, use % em vez disso
-- SELECT 10 % 3; -- Resultado: 1
Funções de Data
NOW — Data e Hora Atual
SELECT NOW(); -- Resultado: 2026-06-28 14:30:00 (hora atual)
SELECT CURDATE(); -- Resultado: 2026-06-28 (apenas data)
SELECT CURTIME(); -- Resultado: 14:30:00 (apenas hora)
GETDATE() em vez de NOW().
DATE — Extrair Parte da Data
SELECT DATE(NOW()); -- Resultado: 2026-06-28
-- Extrair ano, mês, dia
SELECT EXTRACT(YEAR FROM order_date) AS ano,
EXTRACT(MONTH FROM order_date) AS mes,
EXTRACT(DAY FROM order_date) AS dia
FROM orders;
DATEDIFF — Diferença de Datas
-- Calcular o número de dias entre duas datas
SELECT DATEDIFF('2026-12-31', '2026-01-01'); -- Resultado: 364
-- Calcular o tempo de serviço do funcionário em dias
SELECT first_name, hire_date,
DATEDIFF(CURDATE(), hire_date) AS dias_servico
FROM employees;
DATEDIFF(date1, date2) do MySQL calcula date1 - date2. SQL Server usa a mesma ordem. PostgreSQL usa date1 - date2 para subtração direta.
DATE_FORMAT — Formatação de Data
-- MySQL
SELECT DATE_FORMAT(order_date, '%Y-%m-%d') AS data_formatada
FROM orders;
-- SQL Server
-- SELECT FORMAT(order_date, 'yyyy-MM-dd') FROM orders;
EXTRACT — Extrair Partes da Data
SELECT EXTRACT(YEAR FROM order_date) AS ano,
EXTRACT(MONTH FROM order_date) AS mes,
EXTRACT(DAY FROM order_date) AS dia,
EXTRACT(HOUR FROM NOW()) AS hora
FROM orders;
Conversão de Tipo
CAST — Conversão de Tipo (SQL Padrão)
-- String para inteiro
SELECT CAST('123' AS SIGNED INTEGER); -- MySQL
SELECT CAST('123' AS INT); -- SQL Server
-- Número para string
SELECT CAST(12345 AS CHAR);
-- Data para string
SELECT CAST(order_date AS CHAR) FROM orders;
-- String para data
SELECT CAST('2026-06-28' AS DATE);
CONVERT — Conversão de Tipo (MySQL / SQL Server)
-- MySQL
SELECT CONVERT('123', SIGNED INTEGER);
SELECT CONVERT(123, CHAR);
-- SQL Server
SELECT CONVERT(INT, '123');
SELECT CONVERT(VARCHAR, 12345);
CAST é o padrão SQL e possui melhor compatibilidade — é recomendado. CONVERT possui diferenças significativas de sintaxe entre bancos de dados.
📝 Sintaxe Básica
-- Funções de string
SELECT CONCAT(string1, string2) AS concatenado,
SUBSTRING(string, posicao_inicial, comprimento) AS extraido,
UPPER(string) AS maiusculo,
LOWER(string) AS minusculo,
TRIM(string) AS sem_espacos,
REPLACE(string, valor_antigo, valor_novo) AS substituido,
LENGTH(string) AS comprimento;
-- Funções numéricas
SELECT ROUND(numero, casas_decimais) AS arredondado,
CEIL(numero) AS arredondado_cima,
FLOOR(numero) AS arredondado_baixo,
ABS(numero) AS absoluto,
MOD(numero1, numero2) AS resto;
-- Funções de data
SELECT NOW() AS hora_atual,
CURDATE() AS data_atual,
DATEDIFF(data1, data2) AS diferenca_dias,
EXTRACT(YEAR FROM data) AS ano;
-- Conversão de tipo
SELECT CAST(valor AS tipo_destino) AS convertido;
- Nomes e parâmetros de funções podem diferir entre bancos de dados — verifique a documentação do banco correspondente antes de usar
CASTé o padrão SQL e é recomendado;CONVERTtem sintaxe diferente no MySQL e SQL Server- Funções de data possuem as maiores diferenças — preste atenção especial ao desenvolver entre bancos de dados
📌 Exemplos
Exemplo: Processamento de String — Formatação de Informações de Funcionários
SELECT
CONCAT(UPPER(last_name), ', ', first_name) AS nome,
LOWER(email) AS email,
SUBSTRING(phone, 1, 3) AS codigo_area,
LENGTH(first_name) AS comprimento_primeiro_nome,
REPLACE(department_id, NULL, 'Não atribuído') AS departamento
FROM employees
ORDER BY last_name;
Saída:
nome email codigo_area comprimento_primeiro_nome departamento
----------- ---------------------- ----------- ------------------------- ------------
LI, Si lisi@company.com 138 2 2
WANG, Wu wangwu@company.com 139 2 2
ZHANG, San zhangsan@company.com 137 2 1
CONCAT + UPPER formata o nome, LOWER padroniza o e-mail para minúsculas, SUBSTRING extrai os 3 primeiros dígitos do número de telefone.
Exemplo: Cálculo Numérico — Processamento de Valor de Pedidos
SELECT
order_id,
total_amount AS valor_original,
ROUND(total_amount * 0.9, 2) AS valor_com_desconto,
CEIL(total_amount / 1000) AS milhares_cima,
FLOOR(total_amount / 1000) AS milhares_baixo,
MOD(total_amount, 100) AS resto
FROM orders
WHERE status = 'completed';
Saída:
order_id valor_original valor_com_desconto milhares_cima milhares_baixo resto
-------- -------------- ------------------ ------------- -------------- -----
1 15000.00 13500.00 15 15 0.00
2 8500.00 7650.00 9 8 0.00
3 3200.00 2880.00 4 3 0.00
ROUND calcula o preço com desconto de 10%, CEIL e FLOOR arredondam para cima e para baixo no milhar mais próximo, MOD calcula o resto.
Exemplo: Cálculo de Data + Conversão de Tipo
SELECT
first_name AS nome,
hire_date AS data_contratacao,
DATEDIFF(CURDATE(), hire_date) AS dias_servico,
EXTRACT(YEAR FROM hire_date) AS ano_contratacao,
CONCAT(CAST(salary AS CHAR), ' reais') AS salario_exibicao,
DATE_FORMAT(hire_date, '%Y-%m') AS mes_contratacao
FROM employees
ORDER BY hire_date;
Saída:
nome data_contratacao dias_servico ano_contratacao salario_exibicao mes_contratacao
------ ---------------- ------------ --------------- ---------------- ---------------
Zhang 2023-03-15 1199 2023 15000.00 reais 2023-03
Li 2023-07-01 1089 2023 18000.00 reais 2023-07
Wang 2024-01-10 899 2024 12000.00 reais 2024-01
DATEDIFF calcula o tempo de serviço em dias, EXTRACT extrai o ano, CAST converte o salário para string antes de concatenar a unidade, DATE_FORMAT formata a data.
🎬 Cenários de Prática
Cenário 1: Limpeza de Dados — Padronizando Formatos
Os dados no banco possuem formatos inconsistentes e precisam ser limpos para exibição.
SELECT
employee_id,
CONCAT(UPPER(TRIM(last_name)), ', ', TRIM(first_name)) AS nome_padrao,
LOWER(TRIM(email)) AS email_padrao,
REPLACE(REPLACE(phone, '-', ''), ' ', '') AS telefone_padrao,
CAST(salary AS DECIMAL(10,2)) AS salario_padrao
FROM employees
WHERE email IS NOT NULL;
TRIM remove espaços extras, UPPER/LOWER padroniza maiúsculas/minúsculas, REPLACE limpa caracteres especiais de números de telefone, CAST garante tipos de dados consistentes.
Cenário 2: Estatísticas de Relatório — Análise Baseada em Tempo
Analise dados de pedidos por trimestre.
SELECT
EXTRACT(YEAR FROM order_date) AS ano,
CEIL(EXTRACT(MONTH FROM order_date) / 3.0) AS trimestre,
COUNT(*) AS qtd_pedidos,
ROUND(SUM(total_amount), 2) AS valor_total,
ROUND(AVG(total_amount), 2) AS valor_medio_pedido,
DATEDIFF(MAX(order_date), MIN(order_date)) AS dias_periodo
FROM orders
WHERE status != 'cancelled'
GROUP BY EXTRACT(YEAR FROM order_date), CEIL(EXTRACT(MONTH FROM order_date) / 3.0)
ORDER BY ano, trimestre;
CEIL(MONTH / 3.0) converte meses em trimestres (1-3→T1, 4-6→T2, etc.). DATEDIFF calcula o intervalo de tempo de cada trimestre.
❓ Perguntas Frequentes
P: O que acontece quando CONCAT encontra NULL? R: No MySQL,
CONCATretorna NULL quando encontra NULL. Para tratar NULL como string vazia, useCOALESCE:CONCAT(COALESCE(first_name, ''), ' ', last_name). No PostgreSQL, o operador||também retorna NULL ao encontrar NULL.
P: Qual a diferença entre ROUND e CEIL/FLOOR? R:
ROUNDarredonda para um número especificado de casas decimais,CEILarredonda para cima no inteiro mais próximo, eFLOORarredonda para baixo no inteiro mais próximo. Por exemplo, 3.5:ROUND(3.5)= 4,CEIL(3.1)= 4,FLOOR(3.9)= 3.
P: Funções de data são muito diferentes entre bancos de dados? R: Sim, as diferenças são significativas. MySQL usa
NOW(),DATEDIFF(),DATE_FORMAT(); SQL Server usaGETDATE(),DATEDIFF(),FORMAT(); PostgreSQL usaNOW(), subtração de datas,TO_CHAR(). Consulte a documentação correspondente ao desenvolver entre bancos de dados.
P: Devo usar CAST ou CONVERT? R: Use
CAST— é o padrão SQL e suportado por todos os principais bancos de dados.CONVERTtem sintaxe diferente no MySQL e SQL Server, resultando em menor compatibilidade.
📖 Resumo
| Categoria | Funções Comuns | Finalidade |
|---|---|---|
| String | CONCAT, SUBSTRING, UPPER, LOWER, TRIM, REPLACE, LENGTH | Concatenação, extração, conversão, limpeza |
| Numérico | ROUND, CEIL, FLOOR, ABS, MOD | Arredondamento, piso, módulo |
| Data | NOW, CURDATE, DATEDIFF, EXTRACT, DATE_FORMAT | Obter tempo, calcular diferenças, extrair partes |
| Conversão de Tipo | CAST, CONVERT | Conversão de tipo de dado |
- Funções de string são usadas para limpeza e formatação de dados
- Funções numéricas são usadas para cálculos matemáticos e controle de precisão
- Funções de data são usadas para cálculos de tempo e estatísticas de relatórios
CASTé a função de conversão de tipo SQL padrão e é recomendada- Nomes e sintaxe de funções podem diferir entre bancos de dados — esteja atento ao desenvolver entre bancos de dados
📝 Exercícios
Exercício 1 (⭐): Consulte a tabela employees, concatene first_name e last_name em um nome completo (maiúsculas), e calcule o tempo de serviço de cada pessoa em dias.
Exercício 2 (⭐⭐): Consulte a tabela orders, agregue a contagem de pedidos e o valor total por mês, usando EXTRACT para extrair ano e mês, e ROUND para manter 2 casas decimais.
Exercício 3 (⭐⭐⭐): Consulte a tabela employees para gerar um "cartão de visita do funcionário" com o formato: [Departamento] Nome (Ano de Contratação) - Salário Mensal: xxxxx reais. Use funções de string para concatenação e CAST para converter números em strings.
Próxima Lição
👉 16-case-when - Expressões Condicionais: Aprenda expressões condicionais CASE WHEN e domine a lógica condicional no SQL!



