Tipos de Dados: Caracteres
VARCHAR2 - Tipo Recomendado para Strings
VARCHAR2 é o tipo de dado mais usado para armazenar strings de tamanho variável no Oracle.
Sintaxe e Limites:
-- Tamanho em bytes (padrão)
nome VARCHAR2(100)
-- Tamanho em caracteres (recomendado para Unicode)
nome VARCHAR2(100 CHAR)
-- Limites:
-- Mínimo: 1 byte
-- Máximo: 4000 bytes (ou 32767 em PL/SQL)
VARCHAR2 vs VARCHAR
Use sempre VARCHAR2!
- VARCHAR2 é o padrão Oracle
- VARCHAR está reservado para futuro uso
- Comportamento do VARCHAR pode mudar
- VARCHAR2 armazena valores NULL corretamente
BYTE vs CHAR
Cuidado com caracteres multibyte!
- BYTE: tamanho em bytes (padrão)
- CHAR: tamanho em caracteres
- 1 caractere pode ocupar até 4 bytes (UTF-8)
- Use CHAR para evitar problemas
-- Exemplo prático
CREATE TABLE clientes (
id NUMBER(10) PRIMARY KEY,
nome VARCHAR2(100 CHAR), -- Recomendado: usa CHAR
email VARCHAR2(255), -- 255 bytes é suficiente para email
descricao VARCHAR2(4000 CHAR) -- Textos maiores
);
-- Testando BYTE vs CHAR
INSERT INTO clientes VALUES (1, 'João', 'joao@email.com', 'Cliente VIP');
INSERT INTO clientes VALUES (2, '日本語テスト', 'teste@email.com', 'Teste Unicode');
CHAR - Tamanho Fixo
CHAR armazena strings de tamanho fixo, completando com espaços se necessário.
-- Sintaxe
codigo_uf CHAR(2) -- Sempre ocupa 2 bytes
-- Exemplos de uso adequado:
CREATE TABLE enderecos (
uf CHAR(2), -- 'SP', 'RJ' - sempre 2 caracteres
cep CHAR(8), -- '01310100' - sempre 8 dígitos
sexo CHAR(1), -- 'M' ou 'F'
tipo_pessoa CHAR(1) -- 'F' (física) ou 'J' (jurídica)
);
-- CUIDADO: CHAR preenche com espaços!
INSERT INTO enderecos VALUES ('SP', '01310100', 'M', 'F');
-- Comparação com VARCHAR2
SELECT * FROM enderecos WHERE uf = 'SP'; -- Funciona
SELECT * FROM enderecos WHERE uf = 'SP '; -- Também funciona (trailing spaces)
Quando Usar CHAR vs VARCHAR2?
- CHAR: Códigos de tamanho fixo (UF, flags, status com 1 char)
- VARCHAR2: Todos os outros casos (nomes, descrições, emails)
Tipos de Dados: Numéricos
NUMBER - Tipo Universal para Números
NUMBER armazena números com precisão fixa ou flutuante.
Sintaxe: NUMBER(p, s)
- p (precision): Total de dígitos significativos (1 a 38)
- s (scale): Dígitos após a vírgula (-84 a 127)
-- Diversos formatos de NUMBER
CREATE TABLE exemplos_number (
-- Inteiros
id NUMBER(10), -- Até 10 dígitos: 9999999999
quantidade NUMBER(6), -- Até 999999
-- Decimais
preco NUMBER(10, 2), -- 99999999.99 (preço/dinheiro)
peso NUMBER(8, 3), -- 99999.999 (medidas precisas)
percentual NUMBER(5, 2), -- 100.00 (0% a 100%)
-- Sem especificação (até 38 dígitos)
valor_generico NUMBER, -- Qualquer número
-- Escala negativa (arredonda)
populacao NUMBER(10, -3) -- Arredonda para milhares: 1234000
);
-- Exemplos de inserção
INSERT INTO exemplos_number VALUES (
1, -- id
150, -- quantidade
1234.56, -- preco
75.350, -- peso
15.75, -- percentual
123456789.123456, -- valor_generico
1234567 -- populacao (armazenado como 1235000)
);
-- Testando arredondamento
SELECT
populacao, -- 1235000
populacao / 1000 AS milhares -- 1235
FROM exemplos_number;
Boas Práticas com NUMBER
Recomendações
- Sempre especifique precisão e escala
- Use NUMBER(10,2) para valores monetários
- Evite NUMBER sem parâmetros em produção
- Para IDs, use NUMBER(10) ou NUMBER(19)
Evite
- INTEGER (use NUMBER com precisão)
- FLOAT, REAL (use NUMBER para precisão)
- NUMBER sem especificação em tabelas
- Escala maior que precisão
Tipos de Dados: Data e Hora
DATE - Data e Hora
DATE armazena data e hora com precisão de segundos.
-- Criando tabela com DATE
CREATE TABLE eventos (
id NUMBER(10) PRIMARY KEY,
nome VARCHAR2(200 CHAR),
data_criacao DATE DEFAULT SYSDATE,
data_evento DATE,
data_atualizacao DATE
);
-- Inserindo datas de diversas formas
INSERT INTO eventos VALUES (
1,
'Reunião',
SYSDATE, -- Data/hora atual
DATE '2025-01-15', -- Formato ISO (apenas data)
TO_DATE('15/01/2025 14:30', 'DD/MM/YYYY HH24:MI') -- Com hora
);
-- Operações com DATE
SELECT
nome,
data_evento,
data_evento + 7 AS uma_semana_depois, -- Adiciona 7 dias
data_evento - 1 AS ontem, -- Subtrai 1 dia
SYSDATE - data_criacao AS dias_desde_criacao,
TRUNC(data_evento) AS data_sem_hora, -- Remove hora
TO_CHAR(data_evento, 'DD/MM/YYYY HH24:MI:SS') AS formatado
FROM eventos;
TIMESTAMP - Precisão de Frações de Segundo
TIMESTAMP estende DATE com precisão de até 9 casas decimais (nanossegundos).
-- Tipos de TIMESTAMP
CREATE TABLE logs_sistema (
id NUMBER(19) PRIMARY KEY,
mensagem VARCHAR2(4000 CHAR),
timestamp_local TIMESTAMP(6), -- Precisão de 6 casas decimais
timestamp_tz TIMESTAMP WITH TIME ZONE, -- Com fuso horário
timestamp_ltz TIMESTAMP WITH LOCAL TIME ZONE -- Convertido para fuso local
);
-- Inserindo timestamps
INSERT INTO logs_sistema VALUES (
1,
'Sistema iniciado',
SYSTIMESTAMP, -- Timestamp atual
CURRENT_TIMESTAMP, -- Com fuso horário
TO_TIMESTAMP('2025-01-15 10:30:45.123456', 'YYYY-MM-DD HH24:MI:SS.FF6')
);
-- Comparando DATE e TIMESTAMP
SELECT
SYSDATE AS data_atual, -- 15/01/2025 10:30:45
SYSTIMESTAMP AS timestamp_atual -- 15/01/2025 10:30:45.123456000 -03:00
FROM dual;
Quando usar DATE?
- Datas de nascimento, eventos
- Precisão de segundos é suficiente
- Economiza espaço (7 bytes)
Quando usar TIMESTAMP?
- Logs de sistema e auditoria
- Precisa de milissegundos/nanossegundos
- Sistemas distribuídos (time zones)
Large Objects (LOBs)
CLOB e BLOB - Objetos Grandes
CLOB (Character LOB)
Armazena textos muito grandes (até 4 GB).
- Documentos HTML/XML
- Descrições longas
- JSON grandes
- Logs de texto extensos
BLOB (Binary LOB)
Armazena dados binários grandes (até 4 GB).
- Imagens, fotos
- PDFs, documentos
- Vídeos, áudios
- Arquivos compactados
-- Criando tabela com LOBs
CREATE TABLE documentos (
id NUMBER(10) PRIMARY KEY,
titulo VARCHAR2(200 CHAR),
conteudo_xml CLOB, -- Texto grande
arquivo_pdf BLOB, -- Binário grande
data_upload TIMESTAMP DEFAULT SYSTIMESTAMP
);
-- Inserindo texto grande (CLOB)
INSERT INTO documentos (id, titulo, conteudo_xml) VALUES (
1,
'Contrato de Serviço',
'
...
... (muitas linhas) ...
'
);
-- Consultar tamanho dos LOBs
SELECT
titulo,
DBMS_LOB.GETLENGTH(conteudo_xml) AS tamanho_xml_bytes,
DBMS_LOB.GETLENGTH(arquivo_pdf) AS tamanho_pdf_bytes
FROM documentos;
Importante sobre LOBs:
- LOBs são armazenados fora da linha (out-of-line) por padrão
- Use DBMS_LOB package para manipular LOBs grandes
- VARCHAR2(4000) é mais eficiente que CLOB para textos pequenos
- Considere armazenar arquivos no filesystem e apenas referências no BD
Conversões de Tipos
Conversões Implícitas vs Explícitas
Conversão Implícita
Oracle converte automaticamente. Pode causar problemas!
-- Oracle converte automaticamente
SELECT * FROM funcionarios
WHERE id = '123'; -- String → Number
SELECT * FROM eventos
WHERE data_evento = '15/01/2025'; -- String → Date
Conversão Explícita
Use funções TO_*. Recomendado!
-- Conversão explícita e segura
SELECT * FROM funcionarios
WHERE id = TO_NUMBER('123');
SELECT * FROM eventos
WHERE data_evento = TO_DATE('15/01/2025', 'DD/MM/YYYY');
TO_CHAR - Convertendo para String
-- Convertendo números para string
SELECT
TO_CHAR(12345) AS simples, -- '12345'
TO_CHAR(12345, '99999') AS com_formato, -- ' 12345' (com espaços)
TO_CHAR(12345, '00000') AS com_zeros, -- '012345'
TO_CHAR(1234.56, '9999.99') AS decimal, -- '1234.56'
TO_CHAR(1234.56, 'L9,999.99') AS moeda, -- 'R$1,234.56'
TO_CHAR(0.15, '99.99%') AS percentual -- '15.00%'
FROM dual;
-- Convertendo datas para string
SELECT
TO_CHAR(SYSDATE, 'DD/MM/YYYY') AS data_br, -- '15/01/2025'
TO_CHAR(SYSDATE, 'DD/MM/YYYY HH24:MI:SS') AS completo, -- '15/01/2025 14:30:45'
TO_CHAR(SYSDATE, 'DAY, DD "de" MONTH "de" YYYY') AS extenso, -- 'MONDAY, 15 de JANUARY de 2025'
TO_CHAR(SYSDATE, 'DY') AS dia_semana, -- 'MON'
TO_CHAR(SYSDATE, 'Q') AS trimestre, -- '1'
TO_CHAR(SYSDATE, 'YYYY-MM-DD"T"HH24:MI:SS') AS iso -- '2025-01-15T14:30:45'
FROM dual;
TO_NUMBER - Convertendo para Número
-- Convertendo strings para números
SELECT
TO_NUMBER('12345') AS simples, -- 12345
TO_NUMBER('1,234.56', '9,999.99') AS formatado, -- 1234.56
TO_NUMBER('R$1.234,56', 'L9G999D99') AS moeda_br, -- 1234.56
TO_NUMBER('15%', '99%') AS percentual -- 15
FROM dual;
-- CUIDADO com erros!
SELECT TO_NUMBER('ABC') FROM dual; -- ORA-01722: invalid number
-- Use validação com REGEXP_LIKE
SELECT
CASE
WHEN REGEXP_LIKE('12345', '^\d+$')
THEN TO_NUMBER('12345')
ELSE NULL
END AS numero_valido
FROM dual;
TO_DATE e TO_TIMESTAMP - Convertendo para Data
-- TO_DATE: String → Date
SELECT
TO_DATE('15/01/2025', 'DD/MM/YYYY') AS data_br,
TO_DATE('2025-01-15', 'YYYY-MM-DD') AS data_iso,
TO_DATE('15-JAN-2025', 'DD-MON-YYYY') AS data_mon,
TO_DATE('15/01/2025 14:30:45', 'DD/MM/YYYY HH24:MI:SS') AS com_hora
FROM dual;
-- TO_TIMESTAMP: String → Timestamp (com frações de segundo)
SELECT
TO_TIMESTAMP('15/01/2025 14:30:45.123456', 'DD/MM/YYYY HH24:MI:SS.FF6') AS ts,
TO_TIMESTAMP_TZ('2025-01-15 10:30:45 -03:00', 'YYYY-MM-DD HH24:MI:SS TZH:TZM') AS ts_tz
FROM dual;
-- Formatos comuns
-- DD = dia (01-31)
-- MM = mês (01-12)
-- YYYY = ano (4 dígitos)
-- HH24 = hora 24h (00-23)
-- MI = minuto (00-59)
-- SS = segundo (00-59)
-- FF = fração de segundo
Nunca Confie em Conversão Implícita de Datas!
Formatos de data variam por configuração (NLS_DATE_FORMAT). Sempre use TO_DATE explicitamente!
Resultado Esperado
O que você deve dominar após este tópico:
Escolher tipos corretos
VARCHAR2, NUMBER, DATE, TIMESTAMP, LOBs
Especificar precisão
VARCHAR2(100 CHAR), NUMBER(10,2)
Diferenças importantes
CHAR vs VARCHAR2, DATE vs TIMESTAMP
Conversões explícitas
TO_CHAR, TO_NUMBER, TO_DATE
Formatar dados
Usar máscaras de formato corretamente
LOBs quando necessário
CLOB e BLOB para dados grandes