Definição
O que é uma VIEW?
Uma VIEW é uma consulta SQL armazenada que atua como uma tabela virtual. Ela não armazena dados fisicamente, mas apresenta dados de uma ou mais tabelas base através de uma consulta SELECT predefinida.
Características Principais:
- Tabela virtual: Apresenta dados sem armazená-los fisicamente
- Simplificação: Oculta complexidade de consultas com múltiplos JOINs
- Segurança: Restringe acesso a colunas ou linhas específicas
- Consistência: Garante que todos usem a mesma lógica de consulta
- Independência: Protege aplicações de mudanças na estrutura das tabelas
O que é um SYNONYM?
Um SYNONYM é um alias ou apelido para um objeto do banco de dados (tabela, view, sequence, etc.). Facilita o acesso a objetos com nomes longos ou localizados em outros schemas.
Tipos de Synonyms:
SYNONYM Privado
Visível apenas para o usuário que o criou
PUBLIC SYNONYM
Visível para todos os usuários do banco
Aplicação Prática
Criando Views Simples
-- VIEW simples: funcionários ativos com informações básicas
CREATE VIEW vw_funcionarios_ativos AS
SELECT
id_funcionario,
nome,
email,
cargo_id,
departamento_id,
salario,
data_admissao
FROM funcionarios
WHERE status = 'ATIVO';
-- Usando a VIEW como se fosse uma tabela
SELECT * FROM vw_funcionarios_ativos;
SELECT nome, salario FROM vw_funcionarios_ativos WHERE departamento_id = 10;
Views Complexas com JOINs
-- VIEW complexa: relatório completo de funcionários
CREATE VIEW vw_funcionarios_completo AS
SELECT
f.id_funcionario,
f.nome AS funcionario,
f.email,
f.salario,
f.data_admissao,
d.nome_departamento,
d.localizacao,
c.titulo_cargo,
c.salario_minimo AS cargo_salario_min,
c.salario_maximo AS cargo_salario_max,
m.nome AS gerente,
CASE
WHEN f.salario < c.salario_minimo THEN 'Abaixo do mínimo'
WHEN f.salario > c.salario_maximo THEN 'Acima do máximo'
ELSE 'Dentro da faixa'
END AS situacao_salarial
FROM funcionarios f
LEFT JOIN departamentos d ON f.departamento_id = d.id_departamento
LEFT JOIN cargos c ON f.cargo_id = c.id_cargo
LEFT JOIN funcionarios m ON f.gerente_id = m.id_funcionario
WHERE f.status = 'ATIVO';
-- Consulta simplificada usando a VIEW
SELECT funcionario, departamento, salario, situacao_salarial
FROM vw_funcionarios_completo
WHERE situacao_salarial = 'Abaixo do mínimo';
CREATE OR REPLACE VIEW
Use CREATE OR REPLACE para modificar uma VIEW existente sem perder as permissões concedidas.
-- Substituir VIEW existente (mantém permissões)
CREATE OR REPLACE VIEW vw_funcionarios_ativos AS
SELECT
id_funcionario,
nome,
email,
cargo_id,
departamento_id,
ROUND(salario, 0) AS salario, -- Arredonda salário
data_admissao,
FLOOR(MONTHS_BETWEEN(SYSDATE, data_admissao) / 12) AS anos_empresa
FROM funcionarios
WHERE status = 'ATIVO';
-- Se usar DROP VIEW e depois CREATE VIEW, perde as permissões:
-- DROP VIEW vw_funcionarios_ativos; -- ❌ Evite isso!
-- CREATE VIEW vw_funcionarios_ativos AS ...; -- Perdeu GRANTS!
WITH CHECK OPTION
O WITH CHECK OPTION impede que operações DML (INSERT, UPDATE, DELETE) violem a condição WHERE da VIEW.
-- VIEW com CHECK OPTION
CREATE OR REPLACE VIEW vw_funcionarios_depto_ti AS
SELECT
id_funcionario,
nome,
email,
salario,
departamento_id
FROM funcionarios
WHERE departamento_id = 10
WITH CHECK OPTION CONSTRAINT ck_depto_ti;
-- Permitido: UPDATE dentro da condição da VIEW
UPDATE vw_funcionarios_depto_ti
SET salario = 8000
WHERE id_funcionario = 100;
-- BLOQUEADO: Tentativa de mudar para outro departamento
UPDATE vw_funcionarios_depto_ti
SET departamento_id = 20
WHERE id_funcionario = 100;
-- ORA-01402: view WITH CHECK OPTION where-clause violation
Views Atualizáveis vs Não Atualizáveis
View Atualizável
Permite INSERT, UPDATE e DELETE se:
- Baseada em uma única tabela
- Não contém funções de agregação (SUM, AVG, COUNT, etc.)
- Não usa DISTINCT, GROUP BY, ou HAVING
- Não usa operadores de conjunto (UNION, INTERSECT, MINUS)
-- VIEW ATUALIZÁVEL (baseada em uma tabela)
CREATE OR REPLACE VIEW vw_depto_ti AS
SELECT id_funcionario, nome, email, salario
FROM funcionarios
WHERE departamento_id = 10;
-- Operações DML funcionam
INSERT INTO vw_depto_ti VALUES (201, 'João Silva', 'joao@empresa.com', 7000);
UPDATE vw_depto_ti SET salario = 7500 WHERE id_funcionario = 201;
DELETE FROM vw_depto_ti WHERE id_funcionario = 201;
-- VIEW NÃO ATUALIZÁVEL (usa JOIN e agregação)
CREATE OR REPLACE VIEW vw_estatisticas_depto AS
SELECT
d.nome_departamento,
COUNT(*) AS qtd_funcionarios,
AVG(f.salario) AS salario_medio
FROM funcionarios f
JOIN departamentos d ON f.departamento_id = d.id_departamento
GROUP BY d.nome_departamento;
-- Tentativa de UPDATE falha
UPDATE vw_estatisticas_depto SET salario_medio = 8000;
-- ORA-01732: data manipulation operation not legal on this view
Gerenciando Views
-- Remover uma VIEW
DROP VIEW vw_funcionarios_ativos;
-- Consultar definição de uma VIEW
SELECT text
FROM user_views
WHERE view_name = 'VW_FUNCIONARIOS_COMPLETO';
-- Listar todas as VIEWs do usuário
SELECT view_name, text_length, read_only
FROM user_views
ORDER BY view_name;
-- Ver dependências de uma VIEW
SELECT name, type, referenced_name, referenced_type
FROM user_dependencies
WHERE name = 'VW_FUNCIONARIOS_COMPLETO';
Criando Synonyms
-- SYNONYM privado (apenas para o usuário atual)
CREATE SYNONYM func FOR funcionarios;
CREATE SYNONYM depto FOR departamentos;
-- Usando o synonym
SELECT * FROM func WHERE departamento_id = 10;
SELECT * FROM depto;
-- PUBLIC SYNONYM (visível para todos) - requer privilégio
CREATE PUBLIC SYNONYM empresa_func FOR hr.funcionarios;
-- SYNONYM para objetos em outros schemas
CREATE SYNONYM vendas_tab FOR vendas_schema.pedidos;
-- SYNONYM para VIEW
CREATE SYNONYM rel_func FOR vw_funcionarios_completo;
Gerenciando Synonyms
-- Remover SYNONYM privado
DROP SYNONYM func;
-- Remover PUBLIC SYNONYM (requer privilégio)
DROP PUBLIC SYNONYM empresa_func;
-- Listar synonyms do usuário
SELECT synonym_name, table_owner, table_name, db_link
FROM user_synonyms
ORDER BY synonym_name;
-- Listar PUBLIC synonyms
SELECT synonym_name, table_owner, table_name
FROM all_synonyms
WHERE owner = 'PUBLIC'
AND table_name LIKE 'FUNCIONARIOS%';
Resultado Esperado
O que você deve dominar após este tópico:
Criar e modificar views
Usar CREATE VIEW e CREATE OR REPLACE VIEW
WITH CHECK OPTION
Proteger integridade de dados em views
Views atualizáveis
Identificar quando uma view permite DML
Criar synonyms
Usar synonyms privados e públicos
Benefícios práticos
Simplificar consultas e melhorar segurança
Gerenciar objetos
Consultar e remover views e synonyms
Exercícios Práticos
Exercício 1: View de Segurança
Crie uma VIEW que exponha dados de funcionários sem revelar informações salariais sensíveis. Inclua nome, email, departamento e tempo de empresa, mas não salário ou comissões.
Ver Solução
CREATE OR REPLACE VIEW vw_funcionarios_publico AS
SELECT
f.id_funcionario,
f.nome,
f.email,
d.nome_departamento,
c.titulo_cargo,
f.data_admissao,
FLOOR(MONTHS_BETWEEN(SYSDATE, f.data_admissao) / 12) AS anos_empresa,
CASE
WHEN MONTHS_BETWEEN(SYSDATE, f.data_admissao) / 12 < 1 THEN 'Novo'
WHEN MONTHS_BETWEEN(SYSDATE, f.data_admissao) / 12 < 5 THEN 'Intermediário'
ELSE 'Veterano'
END AS categoria_tempo
FROM funcionarios f
LEFT JOIN departamentos d ON f.departamento_id = d.id_departamento
LEFT JOIN cargos c ON f.cargo_id = c.id_cargo
WHERE f.status = 'ATIVO';
Exercício 2: View com CHECK OPTION
Crie uma VIEW para funcionários júniores (salário <= 5000) com CHECK OPTION, garantindo que aumentos salariais não violem esse critério através da VIEW.
Ver Solução
CREATE OR REPLACE VIEW vw_funcionarios_junior AS
SELECT
id_funcionario,
nome,
email,
salario,
cargo_id,
departamento_id
FROM funcionarios
WHERE salario <= 5000
AND status = 'ATIVO'
WITH CHECK OPTION CONSTRAINT ck_salario_junior;
-- Teste: permitido (dentro do limite)
UPDATE vw_funcionarios_junior
SET salario = 4800
WHERE id_funcionario = 100;
-- Teste: bloqueado (ultrapassa o limite)
UPDATE vw_funcionarios_junior
SET salario = 6000
WHERE id_funcionario = 100;
-- Erro: ORA-01402
Exercício 3: Synonyms para Integração
Crie synonyms para simplificar o acesso a tabelas de diferentes schemas em um ambiente de integração, onde o schema de produção é PROD_HR e você está em DEV_APP.
Ver Solução
-- Criar synonyms privados para acesso aos dados de produção
CREATE SYNONYM funcionarios FOR prod_hr.funcionarios;
CREATE SYNONYM departamentos FOR prod_hr.departamentos;
CREATE SYNONYM cargos FOR prod_hr.cargos;
CREATE SYNONYM historico_cargos FOR prod_hr.historico_cargos;
-- Criar synonyms para views do schema de produção
CREATE SYNONYM vw_func_completo FOR prod_hr.vw_funcionarios_completo;
-- Agora o código pode usar nomes simples
SELECT * FROM funcionarios WHERE departamento_id = 10;
SELECT * FROM vw_func_completo WHERE situacao_salarial = 'Abaixo do mínimo';
-- Listar todos os synonyms criados
SELECT synonym_name, table_owner, table_name
FROM user_synonyms
ORDER BY synonym_name;