Laboratório: Gerenciamento de Constraints
Objetivo
Praticar a implementação e gerenciamento de diferentes tipos de constraints no PostgreSQL, garantindo a integridade dos dados e regras de negócio.
Ambiente de Teste
-- Schema para o laboratório
CREATE SCHEMA lab_constraints;
-- Tabelas para prática
CREATE TABLE lab_constraints.produtos (
id SERIAL PRIMARY KEY,
codigo VARCHAR(20) UNIQUE,
nome VARCHAR(100) NOT NULL,
preco DECIMAL(10,2),
categoria_id INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE lab_constraints.categorias (
id SERIAL PRIMARY KEY,
nome VARCHAR(50) UNIQUE,
ativa BOOLEAN DEFAULT true
);
Exercícios Práticos
1. Constraints Básicas
-- Primary Key
ALTER TABLE lab_constraints.produtos
ADD CONSTRAINT pk_produtos PRIMARY KEY (id);
-- Unique Constraint
ALTER TABLE lab_constraints.produtos
ADD CONSTRAINT uk_produtos_codigo UNIQUE (codigo);
-- Not Null
ALTER TABLE lab_constraints.produtos
ALTER COLUMN nome SET NOT NULL;
2. Foreign Keys
-- Adicionar Foreign Key com diferentes ações
ALTER TABLE lab_constraints.produtos
ADD CONSTRAINT fk_produtos_categoria
FOREIGN KEY (categoria_id)
REFERENCES lab_constraints.categorias(id)
ON DELETE RESTRICT
ON UPDATE CASCADE;
3. Check Constraints
-- Validação de preço
ALTER TABLE lab_constraints.produtos
ADD CONSTRAINT ck_produtos_preco
CHECK (preco > 0);
-- Validação de código
ALTER TABLE lab_constraints.produtos
ADD CONSTRAINT ck_produtos_codigo
CHECK (codigo ~ '^[A-Z]{2}\d{4}$');
4. Exclusion Constraints
-- Criar extensão btree_gist se necessário
CREATE EXTENSION IF NOT EXISTS btree_gist;
-- Exemplo de constraint de exclusão
CREATE TABLE lab_constraints.eventos (
id SERIAL PRIMARY KEY,
sala_id INTEGER,
periodo tsrange,
EXCLUDE USING gist (
sala_id WITH =,
periodo WITH &&
)
);
Tarefas Práticas
Tarefa 1: Implementação de Regras de Negócio
-- Regra: Produto não pode ser deletado se tiver vendas
CREATE TABLE lab_constraints.vendas (
id SERIAL PRIMARY KEY,
produto_id INTEGER,
quantidade INTEGER,
CONSTRAINT fk_vendas_produto
FOREIGN KEY (produto_id)
REFERENCES lab_constraints.produtos(id)
ON DELETE RESTRICT
);
-- Regra: Quantidade deve ser positiva
ALTER TABLE lab_constraints.vendas
ADD CONSTRAINT ck_vendas_quantidade
CHECK (quantidade > 0);
Tarefa 2: Constraints Dinâmicas
-- Função para validação customizada
CREATE OR REPLACE FUNCTION lab_constraints.validar_preco()
RETURNS trigger AS $$
BEGIN
IF NEW.preco < (
SELECT MIN(preco)
FROM lab_constraints.produtos
WHERE categoria_id = NEW.categoria_id
) * 0.5 THEN
RAISE EXCEPTION 'Preço muito baixo para a categoria';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger para aplicar validação
CREATE TRIGGER trg_validar_preco
BEFORE INSERT OR UPDATE ON lab_constraints.produtos
FOR EACH ROW
EXECUTE FUNCTION lab_constraints.validar_preco();
Tarefa 3: Gerenciamento de Constraints
-- Desabilitar temporariamente
ALTER TABLE lab_constraints.produtos
DISABLE TRIGGER trg_validar_preco;
-- Reabilitar
ALTER TABLE lab_constraints.produtos
ENABLE TRIGGER trg_validar_preco;
-- Remover constraint
ALTER TABLE lab_constraints.produtos
DROP CONSTRAINT IF EXISTS ck_produtos_preco;
Verificação de Constraints
-- Função para listar todas as constraints
CREATE OR REPLACE FUNCTION lab_constraints.listar_constraints()
RETURNS TABLE (
tabela VARCHAR,
constraint_name VARCHAR,
constraint_type VARCHAR,
definition TEXT
) AS $$
BEGIN
RETURN QUERY
SELECT
tc.table_schema || '.' || tc.table_name::VARCHAR,
tc.constraint_name::VARCHAR,
tc.constraint_type::VARCHAR,
pg_get_constraintdef(pgc.oid)::TEXT
FROM information_schema.table_constraints tc
JOIN pg_constraint pgc
ON tc.constraint_name = pgc.conname
WHERE tc.table_schema = 'lab_constraints'
ORDER BY tc.table_name, tc.constraint_name;
END;
$$ LANGUAGE plpgsql;
Boas Práticas
╔════════════════════════════════════════════╗
║ DIRETRIZES DE CONSTRAINTS: ║
║ ✓ Nomes descritivos ║
║ ✓ Documentação clara ║
║ ✓ Performance considerada ║
║ ✓ Validações apropriadas ║
║ ✓ Manutenção planejada ║
╚════════════════════════════════════════════╝
Troubleshooting
Problemas Comuns
Violação de Constraint
-- Verificar dados violando a constraint SELECT * FROM lab_constraints.produtos WHERE preco <= 0;Deadlocks em Foreign Keys
-- Ajustar isolamento SET TRANSACTION ISOLATION LEVEL READ COMMITTED;Performance
-- Analisar impacto EXPLAIN ANALYZE SELECT * FROM lab_constraints.produtos WHERE codigo = 'AB1234';
Scripts de Manutenção
-- Verificar integridade
CREATE OR REPLACE PROCEDURE lab_constraints.verificar_integridade()
AS $$
DECLARE
v_constraint RECORD;
BEGIN
FOR v_constraint IN (
SELECT * FROM lab_constraints.listar_constraints()
) LOOP
EXECUTE 'VALIDATE CONSTRAINT ' || v_constraint.constraint_name ||
' ON ' || v_constraint.tabela;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Critérios de Avaliação
Implementação
Constraints corretamente definidas
Regras de negócio implementadas
Validações funcionando
Performance
Impacto aceitável
Índices apropriados
Otimizações aplicadas
Manutenibilidade
Documentação clara
Nomes consistentes
Scripts de manutenção
Próximos Passos
Explorar constraints avançadas
Implementar casos complexos
Otimizar performance
Automatizar testes
Recursos Adicionais
26 abril 2025