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:

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ó.

SQL
-- 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.

SQL
-- 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

SQL
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

SQL
-- 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

SQL
-- 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

SQL
SELECT first_name, LENGTH(first_name) AS comprimento_nome
FROM employees;

Funções Numéricas

ROUND — Arredondamento

SQL
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

SQL
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
💡 Nota: Os nomes das funções diferem entre bancos de dados. SQL Server usa CEILING(), Oracle usa CEIL().

ABS — Valor Absoluto

SQL
SELECT ABS(-100);    -- Resultado: 100
SELECT ABS(50);      -- Resultado: 50

MOD — Módulo (Resto)

SQL
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

SQL
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)
💡 Nota: SQL Server usa GETDATE() em vez de NOW().

DATE — Extrair Parte da Data

SQL
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

SQL
-- 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;
💡 Nota: O 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

SQL
-- 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

SQL
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)

SQL
-- 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)

SQL
-- MySQL
SELECT CONVERT('123', SIGNED INTEGER);
SELECT CONVERT(123, CHAR);

-- SQL Server
SELECT CONVERT(INT, '123');
SELECT CONVERT(VARCHAR, 12345);
💡 Recomendação: CAST é o padrão SQL e possui melhor compatibilidade — é recomendado. CONVERT possui diferenças significativas de sintaxe entre bancos de dados.


📝 Sintaxe Básica

SQL
-- 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;
💡 Dica:

  • 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; CONVERT tem 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

SQL
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;
▶ Experimente

Saída:

TEXT
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
💡 Interpretação: 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

SQL
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';
▶ Experimente

Saída:

TEXT
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
💡 Interpretação: 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

SQL
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;
▶ Experimente

Saída:

TEXT
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
💡 Interpretação: 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.

SQL
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;
💡 Abordagem: 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.

SQL
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;
💡 Abordagem: 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, CONCAT retorna NULL quando encontra NULL. Para tratar NULL como string vazia, use COALESCE: 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: ROUND arredonda para um número especificado de casas decimais, CEIL arredonda para cima no inteiro mais próximo, e FLOOR arredonda 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 usa GETDATE(), DATEDIFF(), FORMAT(); PostgreSQL usa NOW(), 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. CONVERT tem 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

📝 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!

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%