Views: consultas salvas e reutilizáveis

1. O que são Views? Conceitos Fundamentais

Uma view (visão) é uma tabela virtual baseada em uma consulta SELECT. Diferentemente de uma tabela real, uma view não armazena dados fisicamente — ela armazena apenas a definição da consulta. Quando você consulta uma view, o banco de dados executa a consulta subjacente e retorna os resultados como se fossem de uma tabela.

A principal diferença entre view e tabela real é:
- Tabela real: armazena dados no disco
- View: armazena apenas a consulta SQL; os dados são obtidos das tabelas base no momento da execução

As vantagens principais das views são:
- Segurança: ocultar colunas ou linhas sensíveis de usuários
- Simplificação: encapsular consultas complexas em objetos simples
- Reuso: evitar repetição de consultas em múltiplos lugares

2. Criando e Utilizando Views Básicas

A sintaxe básica para criar uma view é:

CREATE VIEW nome_da_view AS
SELECT coluna1, coluna2, ...
FROM tabela
WHERE condição;

Exemplo prático — view de clientes ativos:

CREATE VIEW clientes_ativos AS
SELECT id_cliente, nome, email, data_cadastro
FROM clientes
WHERE status = 'ativo';

Para consultar a view:

SELECT * FROM clientes_ativos;

Para atualizar uma view existente:

CREATE OR REPLACE VIEW clientes_ativos AS
SELECT id_cliente, nome, email, data_cadastro, telefone
FROM clientes
WHERE status = 'ativo' AND data_cadastro >= '2024-01-01';

3. Views com Lógica Condicional e Junções

Views podem incorporar toda a complexidade do SQL, incluindo junções, agrupamentos e condições.

Exemplo — view de relatório mensal de vendas:

CREATE VIEW relatorio_vendas_mensal AS
SELECT 
    DATE_TRUNC('month', v.data_venda) AS mes,
    p.categoria,
    COUNT(DISTINCT v.id_venda) AS total_vendas,
    SUM(v.quantidade * v.preco_unitario) AS receita_total,
    AVG(v.quantidade * v.preco_unitario) AS ticket_medio
FROM vendas v
JOIN produtos p ON v.id_produto = p.id_produto
WHERE v.status = 'confirmada'
GROUP BY DATE_TRUNC('month', v.data_venda), p.categoria
HAVING SUM(v.quantidade * v.preco_unitario) > 1000;

Views aninhadas — criando views a partir de outras views:

CREATE VIEW vendas_por_categoria AS
SELECT categoria, mes, receita_total
FROM relatorio_vendas_mensal;

CREATE VIEW top_categorias AS
SELECT categoria, SUM(receita_total) AS receita_acumulada
FROM vendas_por_categoria
GROUP BY categoria
ORDER BY receita_acumulada DESC
LIMIT 5;

4. Views Atualizáveis (Updatable Views)

Uma view é atualizável quando permite operações INSERT, UPDATE e DELETE diretamente sobre ela. As condições para isso incluem:
- A view deve ser baseada em uma única tabela (sem JOIN)
- Não pode conter DISTINCT, GROUP BY, HAVING, funções agregadas
- Não pode usar subconsultas na lista SELECT

Exemplo de view atualizável:

CREATE VIEW funcionarios_ativos AS
SELECT id_funcionario, nome, cargo, salario, departamento
FROM funcionarios
WHERE ativo = true;

Atualizando dados via view:

UPDATE funcionarios_ativos
SET salario = salario * 1.10
WHERE departamento = 'TI';

Inserindo via view:

INSERT INTO funcionarios_ativos (nome, cargo, salario, departamento)
VALUES ('Maria Silva', 'Analista', 5000, 'RH');

A cláusula WITH CHECK OPTION garante que as alterações respeitem a condição da view:

CREATE VIEW funcionarios_ativos_com_check AS
SELECT id_funcionario, nome, cargo, salario, departamento
FROM funcionarios
WHERE ativo = true
WITH CHECK OPTION;

Com WITH CHECK OPTION, um UPDATE que torne o funcionário inativo falhará, pois violaria a condição da view.

5. Views vs. Tabelas Temporárias vs. CTEs

A escolha entre view, tabela temporária e CTE depende do cenário:

Característica View Tabela Temporária CTE
Persistência Permanente (definição) Sessão/transação Consulta única
Armazenamento Nenhum (virtual) Temporário em disco Nenhum (virtual)
Reuso Sim, múltiplas consultas Apenas na sessão Apenas na consulta
Performance Executa a cada chamada Materializada uma vez Executa a cada referência

Quando usar cada um:
- View: relatórios frequentes, segurança, abstração de esquema
- Tabela temporária: processamento em etapas, dados intermediários grandes
- CTE: consultas recursivas, legibilidade em consultas complexas únicas

Exemplo de CTE vs view:

-- CTE (uso único)
WITH vendas_2024 AS (
    SELECT * FROM vendas WHERE EXTRACT(YEAR FROM data_venda) = 2024
)
SELECT cliente_id, SUM(valor) FROM vendas_2024 GROUP BY cliente_id;

-- View equivalente (reutilizável)
CREATE VIEW vendas_2024 AS
SELECT * FROM vendas WHERE EXTRACT(YEAR FROM data_venda) = 2024;

6. Gerenciamento e Manutenção de Views

Listando views existentes:

SELECT table_name, view_definition
FROM information_schema.views
WHERE table_schema = 'public';

Alterando e renomeando views:

ALTER VIEW clientes_ativos RENAME TO clientes_ativos_2024;

ALTER VIEW clientes_ativos_2024 SET SCHEMA relatorios;

Excluindo views:

DROP VIEW IF EXISTS clientes_ativos_2024;

Boas práticas:
- Nomeie views com prefixos como v_ ou view_ para identificação
- Documente o propósito e as tabelas base em comentários SQL
- Versionar as definições de view no controle de versão do código
- Evite dependências circulares entre views

7. Considerações de Performance e Segurança

Performance:
- Views não são materializadas por padrão — a consulta é executada a cada acesso
- Índices nas tabelas base melhoram a performance das views
- Views complexas com múltiplos JOIN e agregações podem ser lentas
- Em bancos como PostgreSQL, é possível criar materialized views que armazenam resultados

Segurança:
- Views podem ocultar colunas sensíveis (CPF, senhas, dados bancários)
- Podem filtrar linhas por departamento ou perfil de usuário
- Permitem conceder acesso a dados específicos sem expor tabelas completas

Exemplo de view para mascaramento de dados:

CREATE VIEW clientes_mascarados AS
SELECT 
    id_cliente,
    nome,
    CONCAT(SUBSTRING(cpf, 1, 3), '.***.***-**') AS cpf_parcial,
    email
FROM clientes;

8. Exemplos Práticos Completos

View para dashboard de indicadores de vendas:

CREATE VIEW dashboard_vendas AS
SELECT 
    CURRENT_DATE AS data_referencia,
    COUNT(DISTINCT v.id_venda) AS vendas_hoje,
    SUM(v.valor_total) AS receita_hoje,
    AVG(v.valor_total) AS ticket_medio_hoje,
    COUNT(DISTINCT v.cliente_id) AS clientes_ativos_hoje
FROM vendas v
WHERE v.data_venda::date = CURRENT_DATE;

View para hierarquia de funcionários (recursiva com CTE):

CREATE VIEW hierarquia_funcionarios AS
WITH RECURSIVE hierarquia AS (
    SELECT id, nome, gerente_id, 1 AS nivel, nome AS caminho
    FROM funcionarios
    WHERE gerente_id IS NULL
    UNION ALL
    SELECT f.id, f.nome, f.gerente_id, h.nivel + 1, 
           CONCAT(h.caminho, ' -> ', f.nome)
    FROM funcionarios f
    JOIN hierarquia h ON f.gerente_id = h.id
)
SELECT * FROM hierarquia;

View para compatibilidade entre versões de esquema:

CREATE VIEW clientes_v2 AS
SELECT 
    id_cliente,
    nome_completo AS nome,
    email_principal AS email,
    telefone_celular AS telefone,
    data_nascimento
FROM clientes_v1;

Essa view permite que aplicações que esperam o esquema v2 continuem funcionando enquanto a migração do banco é feita gradualmente.


As views são ferramentas indispensáveis no arsenal de qualquer profissional de banco de dados. Elas oferecem abstração, segurança e reuso, permitindo que consultas complexas sejam tratadas como tabelas simples. Quando usadas com boas práticas e atenção aos limites de performance, as views transformam a maneira como interagimos com os dados, tornando o desenvolvimento mais ágil e os sistemas mais seguros.

Referências