Início / Trilha 1 / Conteúdo / Tópico 12
12

Funções SQL

Numéricas, strings, datas, conversão e condicionais

🔢

Funções Numéricas

Principais Funções para Números

ROUND - Arredondar

Arredonda um número para um número especificado de casas decimais.

SELECT ROUND(123.456, 2) FROM DUAL;      -- 123.46
SELECT ROUND(123.456, 0) FROM DUAL;      -- 123
SELECT ROUND(123.456, -1) FROM DUAL;     -- 120 (arredonda dezenas)
SELECT ROUND(salario, -3) FROM funcionarios;  -- Arredonda para milhares

TRUNC - Truncar

Remove casas decimais sem arredondar.

SELECT TRUNC(123.456, 2) FROM DUAL;      -- 123.45 (sem arredondar)
SELECT TRUNC(123.456, 0) FROM DUAL;      -- 123
SELECT TRUNC(123.456, -1) FROM DUAL;     -- 120

MOD - Módulo (resto da divisão)

SELECT MOD(10, 3) FROM DUAL;             -- 1 (resto de 10÷3)
SELECT MOD(15, 4) FROM DUAL;             -- 3

-- Verificar números pares
SELECT nome, salario
FROM funcionarios
WHERE MOD(salario, 2) = 0;               -- Salários pares

ABS - Valor Absoluto

SELECT ABS(-42) FROM DUAL;               -- 42
SELECT ABS(42) FROM DUAL;                -- 42
SELECT ABS(salario - 5000) FROM funcionarios;  -- Diferença absoluta

CEIL e FLOOR - Arredondar para cima/baixo

SELECT CEIL(123.456) FROM DUAL;          -- 124 (próximo inteiro acima)
SELECT FLOOR(123.456) FROM DUAL;         -- 123 (próximo inteiro abaixo)
SELECT CEIL(-2.3) FROM DUAL;             -- -2
SELECT FLOOR(-2.3) FROM DUAL;            -- -3
🔤

Funções de String (Caracteres)

Conversão de Caso

UPPER, LOWER, INITCAP

SELECT UPPER('oracle database') FROM DUAL;     -- ORACLE DATABASE
SELECT LOWER('ORACLE DATABASE') FROM DUAL;     -- oracle database
SELECT INITCAP('oracle database') FROM DUAL;   -- Oracle Database

-- Busca case-insensitive
SELECT nome FROM funcionarios
WHERE UPPER(nome) = UPPER('joão silva');

Manipulação de Strings

SUBSTR - Extrair Substring

SELECT SUBSTR('Oracle Database', 1, 6) FROM DUAL;     -- Oracle (posição 1, 6 chars)
SELECT SUBSTR('Oracle Database', 8) FROM DUAL;        -- Database (posição 8 até o fim)
SELECT SUBSTR('Oracle Database', -8) FROM DUAL;       -- Database (8 chars do fim)

-- Extrair código de área de telefone
SELECT SUBSTR(telefone, 1, 4) AS ddd FROM clientes;

LENGTH - Tamanho da String

SELECT LENGTH('Oracle') FROM DUAL;                    -- 6
SELECT LENGTH('') FROM DUAL;                          -- NULL (string vazia = NULL)

-- Validar tamanho mínimo de senha
SELECT nome FROM usuarios
WHERE LENGTH(senha) < 8;

CONCAT e || (Concatenação)

SELECT CONCAT('Oracle', ' Database') FROM DUAL;       -- Oracle Database
SELECT 'Oracle' || ' ' || 'Database' FROM DUAL;       -- Oracle Database (operador ||)

-- Montar nome completo
SELECT nome || ' - ' || cargo AS identificacao
FROM funcionarios;

-- Concatenar múltiplas colunas
SELECT CONCAT(CONCAT(nome, ' ('), CONCAT(cargo, ')')) FROM funcionarios;

TRIM, LTRIM, RTRIM - Remover Espaços

SELECT TRIM('   Oracle   ') FROM DUAL;                -- Oracle
SELECT LTRIM('   Oracle   ') FROM DUAL;               -- 'Oracle   '
SELECT RTRIM('   Oracle   ') FROM DUAL;               -- '   Oracle'

-- Remover caracteres específicos
SELECT TRIM('x' FROM 'xxxOraclexxx') FROM DUAL;       -- Oracle

-- Limpar dados de entrada
UPDATE clientes
SET email = TRIM(email)
WHERE email != TRIM(email);

LPAD e RPAD - Preencher com Caracteres

SELECT LPAD('42', 5, '0') FROM DUAL;                  -- 00042
SELECT RPAD('Oracle', 10, '.') FROM DUAL;             -- Oracle....

-- Formatar IDs com zeros à esquerda
SELECT LPAD(id_funcionario, 6, '0') AS codigo_formatado
FROM funcionarios;

-- Criar máscaras
SELECT LPAD(SUBSTR(cpf, -4, 4), LENGTH(cpf), '*') AS cpf_mascarado
FROM clientes;
📅

Funções de Data e Hora

Obter Data Atual

SYSDATE e CURRENT_DATE

SELECT SYSDATE FROM DUAL;                             -- Data/hora do servidor
SELECT CURRENT_DATE FROM DUAL;                        -- Data/hora da sessão

-- Usar em INSERT
INSERT INTO logs (id, mensagem, data_hora)
VALUES (1, 'Sistema iniciado', SYSDATE);

Aritmética com Datas

ADD_MONTHS - Adicionar Meses

SELECT ADD_MONTHS(SYSDATE, 3) FROM DUAL;              -- Daqui a 3 meses
SELECT ADD_MONTHS(SYSDATE, -6) FROM DUAL;             -- Há 6 meses atrás

-- Calcular vencimento de contrato
SELECT nome, data_contratacao,
       ADD_MONTHS(data_contratacao, 12) AS fim_contrato
FROM funcionarios;

MONTHS_BETWEEN - Diferença em Meses

SELECT MONTHS_BETWEEN(SYSDATE, DATE '2020-01-01') FROM DUAL;

-- Calcular tempo de empresa
SELECT nome,
       ROUND(MONTHS_BETWEEN(SYSDATE, data_admissao) / 12, 1) AS anos_empresa
FROM funcionarios;

Operações Aritméticas Diretas

SELECT SYSDATE + 7 FROM DUAL;                         -- Daqui a 7 dias
SELECT SYSDATE - 30 FROM DUAL;                        -- Há 30 dias

-- Diferença entre datas em dias
SELECT nome, SYSDATE - data_admissao AS dias_empresa
FROM funcionarios;

-- Adicionar horas (1/24 = 1 hora)
SELECT SYSDATE + (2/24) FROM DUAL;                    -- Daqui a 2 horas

TRUNC com Datas - Truncar Parte do Tempo

SELECT TRUNC(SYSDATE) FROM DUAL;                      -- Remove hora (00:00:00)
SELECT TRUNC(SYSDATE, 'MM') FROM DUAL;                -- Primeiro dia do mês
SELECT TRUNC(SYSDATE, 'YYYY') FROM DUAL;              -- Primeiro dia do ano
SELECT TRUNC(SYSDATE, 'Q') FROM DUAL;                 -- Primeiro dia do trimestre

-- Comparar apenas datas (sem hora)
SELECT * FROM pedidos
WHERE TRUNC(data_pedido) = TRUNC(SYSDATE);

EXTRACT - Extrair Parte da Data

SELECT EXTRACT(YEAR FROM SYSDATE) FROM DUAL;          -- 2024
SELECT EXTRACT(MONTH FROM SYSDATE) FROM DUAL;         -- 12
SELECT EXTRACT(DAY FROM SYSDATE) FROM DUAL;           -- 17

-- Agrupar vendas por ano
SELECT EXTRACT(YEAR FROM data_venda) AS ano,
       COUNT(*) AS total_vendas
FROM vendas
GROUP BY EXTRACT(YEAR FROM data_venda);
🔄

Funções de Conversão

Conversões de Tipo

TO_CHAR - Converter para String

-- Números para string
SELECT TO_CHAR(12345.67) FROM DUAL;                   -- '12345.67'
SELECT TO_CHAR(12345.67, '999,999.99') FROM DUAL;    -- ' 12,345.67'
SELECT TO_CHAR(12345.67, 'L999,999.99') FROM DUAL;   -- 'R$ 12,345.67' (local)
SELECT TO_CHAR(salario, 'FM999G999G990D00') FROM funcionarios;  -- Formato brasileiro

-- Datas para string
SELECT TO_CHAR(SYSDATE, 'DD/MM/YYYY') FROM DUAL;     -- 17/12/2025
SELECT TO_CHAR(SYSDATE, 'DD/MM/YYYY HH24:MI:SS') FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'Day, DD "de" Month "de" YYYY') FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'DY') FROM DUAL;             -- Seg, Ter, etc.

-- Formatos úteis
SELECT TO_CHAR(data_pedido, 'YYYY-MM') AS mes_ano
FROM pedidos
GROUP BY TO_CHAR(data_pedido, 'YYYY-MM');

TO_NUMBER - Converter String para Número

SELECT TO_NUMBER('12345') FROM DUAL;                  -- 12345
SELECT TO_NUMBER('12,345.67', '99,999.99') FROM DUAL; -- 12345.67

-- Converter e calcular
SELECT TO_NUMBER('100') + TO_NUMBER('200') FROM DUAL; -- 300

-- Útil ao importar dados CSV
UPDATE tabela_temp
SET valor_numerico = TO_NUMBER(valor_string, '999999.99');

TO_DATE - Converter String para Data

SELECT TO_DATE('17/12/2025', 'DD/MM/YYYY') FROM DUAL;
SELECT TO_DATE('2025-12-17', 'YYYY-MM-DD') FROM DUAL;
SELECT TO_DATE('17-DEC-25', 'DD-MON-YY') FROM DUAL;
SELECT TO_DATE('17/12/2025 14:30:00', 'DD/MM/YYYY HH24:MI:SS') FROM DUAL;

-- Usar em condições WHERE
SELECT * FROM pedidos
WHERE data_pedido >= TO_DATE('01/01/2025', 'DD/MM/YYYY')
  AND data_pedido < TO_DATE('01/02/2025', 'DD/MM/YYYY');

Formatos Comuns

Datas:
  • DD/MM/YYYY - 17/12/2025
  • YYYY-MM-DD - 2025-12-17
  • DD-MON-YY - 17-DEC-25
  • HH24:MI:SS - 14:30:00
Números:
  • 999,999.99 - separadores
  • FM - remove espaços
  • L - símbolo da moeda local
  • G - separador de milhar
🔀

Funções Condicionais e NULL

Tratamento de NULL

NVL - Substituir NULL

SELECT NVL(comissao, 0) FROM funcionarios;            -- Se NULL, usa 0
SELECT NVL(telefone, 'Não informado') FROM clientes;  -- Se NULL, usa texto

-- Calcular com NULL tratado
SELECT nome, salario, NVL(comissao, 0) AS comissao,
       salario + NVL(comissao, 0) AS total
FROM funcionarios;

NVL2 - Valor se NULL ou NÃO NULL

-- NVL2(expressão, valor_se_não_null, valor_se_null)
SELECT NVL2(comissao, 'Sim', 'Não') AS tem_comissao
FROM funcionarios;

SELECT nome,
       NVL2(data_demissao, 'Inativo', 'Ativo') AS status
FROM funcionarios;

COALESCE - Primeiro valor não NULL

-- Retorna o primeiro valor não NULL da lista
SELECT COALESCE(telefone_celular, telefone_residencial,
                telefone_comercial, 'Sem telefone') AS contato
FROM clientes;

SELECT COALESCE(email_principal, email_secundario, 'nao@informado.com')
FROM usuarios;

Lógica Condicional

DECODE - Condicional Simples

-- DECODE(coluna, valor1, resultado1, valor2, resultado2, ..., padrão)
SELECT nome,
       DECODE(departamento_id,
              10, 'Tecnologia',
              20, 'RH',
              30, 'Financeiro',
              'Outros') AS departamento
FROM funcionarios;

SELECT nome,
       DECODE(SIGN(salario - 5000),
              1, 'Alto',          -- salario > 5000
              0, 'Médio',         -- salario = 5000
              -1, 'Baixo') AS faixa_salarial
FROM funcionarios;

CASE - Condicional Avançada (SQL Padrão)

-- CASE simples (igual ao DECODE)
SELECT nome,
       CASE departamento_id
           WHEN 10 THEN 'Tecnologia'
           WHEN 20 THEN 'RH'
           WHEN 30 THEN 'Financeiro'
           ELSE 'Outros'
       END AS departamento
FROM funcionarios;

-- CASE com condições complexas (mais poderoso)
SELECT nome, salario,
       CASE
           WHEN salario < 3000 THEN 'Júnior'
           WHEN salario BETWEEN 3000 AND 7000 THEN 'Pleno'
           WHEN salario > 7000 THEN 'Sênior'
           ELSE 'Não classificado'
       END AS nivel
FROM funcionarios;

-- CASE aninhado
SELECT nome,
       CASE
           WHEN departamento_id = 10 THEN
               CASE
                   WHEN salario > 8000 THEN 'TI - Sênior'
                   ELSE 'TI - Júnior'
               END
           WHEN departamento_id = 20 THEN 'RH'
           ELSE 'Outros'
       END AS classificacao
FROM funcionarios;
🛠️

Exemplos Práticos Combinados

Exemplo 1: Relatório de Funcionários Formatado

SELECT
    LPAD(id_funcionario, 6, '0') AS codigo,
    INITCAP(nome) AS funcionario,
    UPPER(cargo) AS cargo,
    TO_CHAR(salario, 'L999G999D00') AS salario_formatado,
    TO_CHAR(data_admissao, 'DD/MM/YYYY') AS admissao,
    ROUND(MONTHS_BETWEEN(SYSDATE, data_admissao) / 12, 1) AS anos_empresa,
    CASE
        WHEN MONTHS_BETWEEN(SYSDATE, data_admissao) / 12 < 1 THEN 'Novo'
        WHEN MONTHS_BETWEEN(SYSDATE, data_admissao) / 12 < 5 THEN 'Experiente'
        ELSE 'Veterano'
    END AS categoria,
    NVL(TO_CHAR(comissao, '999.99'), 'N/A') AS comissao
FROM funcionarios
ORDER BY anos_empresa DESC;

Exemplo 2: Análise de Vendas

SELECT
    EXTRACT(YEAR FROM data_venda) AS ano,
    EXTRACT(MONTH FROM data_venda) AS mes,
    TO_CHAR(data_venda, 'Month') AS nome_mes,
    COUNT(*) AS total_vendas,
    TO_CHAR(SUM(valor), 'L999G999G990D00') AS total_formatado,
    ROUND(AVG(valor), 2) AS ticket_medio,
    CASE
        WHEN SUM(valor) > 100000 THEN 'Excelente'
        WHEN SUM(valor) > 50000 THEN 'Bom'
        ELSE 'Regular'
    END AS performance
FROM vendas
WHERE data_venda >= ADD_MONTHS(TRUNC(SYSDATE, 'YYYY'), -12)
GROUP BY
    EXTRACT(YEAR FROM data_venda),
    EXTRACT(MONTH FROM data_venda),
    TO_CHAR(data_venda, 'Month')
ORDER BY ano DESC, mes DESC;

Exemplo 3: Validação e Limpeza de Dados

SELECT
    id_cliente,
    TRIM(nome) AS nome_limpo,
    UPPER(TRIM(email)) AS email_padronizado,
    CASE
        WHEN LENGTH(TRIM(telefone)) = 11 THEN
            '(' || SUBSTR(telefone, 1, 2) || ') ' ||
            SUBSTR(telefone, 3, 5) || '-' || SUBSTR(telefone, 8, 4)
        ELSE 'Telefone Inválido'
    END AS telefone_formatado,
    CASE
        WHEN email LIKE '%@%' THEN 'Válido'
        ELSE 'Inválido'
    END AS status_email,
    COALESCE(NULLIF(TRIM(endereco), ''), 'Não informado') AS endereco,
    ROUND((SYSDATE - data_cadastro), 0) AS dias_cadastrado,
    DECODE(SIGN(SYSDATE - ultima_compra - 90),
           1, 'Inativo',
           -1, 'Ativo',
           'Cliente Novo') AS status_cliente
FROM clientes;

Resultado Esperado

O que você deve dominar após este tópico:

Funções numéricas

ROUND, TRUNC, MOD, ABS, CEIL, FLOOR

Manipular strings

UPPER, LOWER, SUBSTR, LENGTH, CONCAT, TRIM, LPAD/RPAD

Trabalhar com datas

SYSDATE, ADD_MONTHS, MONTHS_BETWEEN, TRUNC, EXTRACT

Converter tipos

TO_CHAR, TO_NUMBER, TO_DATE com formatos

Tratar NULLs

NVL, NVL2, COALESCE

Lógica condicional

DECODE, CASE para decisões em SQL

📝

Exercícios Práticos

Exercício 1: Formatação de Relatório

Crie uma query que mostre funcionários com: nome em maiúsculas, salário formatado em reais, tempo de empresa em anos (arredondado) e categoria (Júnior/Pleno/Sênior baseado no salário).

Ver Solução
SELECT
    UPPER(nome) AS nome,
    TO_CHAR(salario, 'L999G999D00') AS salario,
    ROUND(MONTHS_BETWEEN(SYSDATE, data_admissao) / 12, 1) AS anos,
    CASE
        WHEN salario < 4000 THEN 'Júnior'
        WHEN salario BETWEEN 4000 AND 8000 THEN 'Pleno'
        ELSE 'Sênior'
    END AS categoria
FROM funcionarios
ORDER BY salario DESC;

Exercício 2: Manipulação de Strings

Extraia os 3 primeiros caracteres do nome, converta para maiúsculas e concatene com o ID formatado com zeros à esquerda (6 dígitos) para criar um código único.

Ver Solução
SELECT
    id_funcionario,
    nome,
    UPPER(SUBSTR(nome, 1, 3)) || LPAD(id_funcionario, 6, '0') AS codigo_unico
FROM funcionarios;

Exercício 3: Análise Temporal

Liste funcionários admitidos nos últimos 90 dias, mostrando nome, data de admissão formatada, dias desde admissão e o dia da semana da admissão.

Ver Solução
SELECT
    nome,
    TO_CHAR(data_admissao, 'DD/MM/YYYY') AS data_admissao,
    ROUND(SYSDATE - data_admissao, 0) AS dias_admitido,
    TO_CHAR(data_admissao, 'Day') AS dia_semana
FROM funcionarios
WHERE data_admissao >= SYSDATE - 90
ORDER BY data_admissao DESC;
Anterior: TCL Próximo: Agregação e GROUP BY