Todo mundo erra, né? Principalmente quando o assunto são os detalhes de foreign keys nos bancos de dados. Nessa aula, vou te ajudar a fugir das armadilhas e dos erros mais frequentes. Um banco de dados bem feito é tipo uma ponte firme: se vacilar em algum lugar, tudo pode desabar. Bora ver como manter suas "pontes de dados" em ordem.
Erro 1: Falta de índice na foreign key
Quando você adiciona uma foreign key, tá dizendo pro banco: "Liga essas tabelas aí". Mas se você não criar um índice nesse campo, quando rolar query pesada envolvendo essas tabelas, a performance pode cair feio.
Exemplo do problema:
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id)
);
Parece tudo certo: tabelas criadas, foreign key no esquema. Mas se você rodar uma query tipo:
SELECT *
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id;
com muitos dados, essa query pode ficar bem lenta, porque o PostgreSQL não vai achar um índice legal pra otimizar o join.
Como evitar:
Sempre cria um índice pro campo referenciado pela foreign key. Às vezes o PostgreSQL faz isso sozinho, mas é melhor garantir.
CREATE INDEX idx_customer_id ON orders(customer_id);
Erro 2: Ordem errada na criação das tabelas
Imagina que você tá criando as tabelas, mas tenta adicionar uma foreign key antes de criar a tabela que ela referencia. O PostgreSQL vai reclamar e jogar erro, porque não acha a tabela alvo.
Exemplo do problema:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id)
);
-- Opa, cadê a tabela customers?..
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
Resultado: o PostgreSQL solta erro, porque a tabela customers ainda não existe.
Como evitar:
Primeiro cria as tabelas que vão ser referenciadas, depois adiciona as foreign keys. A ordem faz diferença. Olha o jeito certo:
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id)
);
Erro 3: Erros de sintaxe nas operações em cascata
Foreign keys geralmente vêm com opções tipo ON DELETE CASCADE ou ON UPDATE RESTRICT. Mas se você vacilar na hora de escrever essas regras, o banco pode se comportar de um jeito estranho. Por exemplo, deletar dados numa tabela não vai afetar as tabelas dependentes.
Exemplo do problema:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADEE
);
Olho vivo: tem um erro de digitação — CASCADEE tá errado. O PostgreSQL não vai deixar passar.
Como evitar:
Escrever certo já é meio caminho andado. Se pintar dúvida, confere sempre na documentação oficial do PostgreSQL.
Erro 4: Quebra de integridade dos dados
Integridade dos dados é sagrado em qualquer banco, e as foreign keys ajudam a manter isso. Mas às vezes a galera esquece de colocar a foreign key, aí vira bagunça.
Exemplo do problema:
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT
);
-- Inserindo dados
INSERT INTO orders (customer_id) VALUES (999);
Aqui a gente adicionou um pedido pra um cliente que nem existe. Isso quebra a integridade dos dados, e esse pedido fica "perdido".
Como evitar:
Sempre usa foreign keys pra evitar que uma tabela aponte pra registros que não existem. Olha o exemplo certo:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id)
);
Agora, se tentar inserir um registro "perdido", vai dar erro.
Erro 5: Ignorar erros de foreign key
Às vezes o dev tenta forçar a barra e inserir dados incompatíveis usando INSERT ... ON CONFLICT. Parece legal, mas com foreign key pode dar ruim.
Exemplo do problema:
INSERT INTO orders (order_id, customer_id)
VALUES (1, 999)
ON CONFLICT DO NOTHING;
Resultado: nada é inserido, mas o banco não te fala o motivo. Você perde o controle da situação.
Como evitar:
Se for usar ON CONFLICT, sempre confere os dados antes. Tipo assim:
INSERT INTO orders (order_id, customer_id)
SELECT 1, 999
WHERE EXISTS (
SELECT 1 FROM customers WHERE customer_id = 999
);
Erro 6: Deletar registros dependentes sem ON DELETE
Se você deleta um registro da tabela referenciada pela foreign key, mas esquece do ON DELETE CASCADE, os registros dependentes ficam lá, quebrando o sentido da relação.
Exemplo do problema:
DELETE FROM customers WHERE customer_id = 1;
-- Os registros em orders com customer_id = 1 ainda ficam lá.
Como evitar:
Adiciona ON DELETE CASCADE pra apagar automaticamente os registros relacionados:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADE
);
Agora, quando você deletar um cliente, os pedidos dele também somem.
Erro 7: Dificuldade com relações MANY-TO-MANY
Quando o assunto é relação MANY-TO-MANY, às vezes a galera esquece de colocar uma chave primária composta ou um índice na tabela.
Exemplo do problema:
CREATE TABLE enrollments (
student_id INT REFERENCES students(student_id),
course_id INT REFERENCES courses(course_id)
);
-- Opa! Esquecemos o PRIMARY KEY.
Como evitar:
Coloca uma chave primária composta ou um índice único:
CREATE TABLE enrollments (
student_id INT REFERENCES students(student_id),
course_id INT REFERENCES courses(course_id),
PRIMARY KEY (student_id, course_id)
);
Erro 8: Referências cíclicas
Referências cíclicas rolam quando duas tabelas apontam uma pra outra como foreign key. Isso vira um ciclo e complica na hora de inserir dados.
Exemplo do problema:
CREATE TABLE table_a (
id SERIAL PRIMARY KEY,
table_b_id INT REFERENCES table_b(id)
);
CREATE TABLE table_b (
id SERIAL PRIMARY KEY,
table_a_id INT REFERENCES table_a(id)
);
Como evitar:
Usa DEFERRABLE INITIALLY DEFERRED pra deixar o PostgreSQL checar a integridade só no fim da transação:
CREATE TABLE table_a (
id SERIAL PRIMARY KEY,
table_b_id INT REFERENCES table_b(id) DEFERRABLE INITIALLY DEFERRED
);
Errar com foreign key não só atrasa o desenvolvimento, mas pode dar dor de cabeça séria nos dados. Usa essa lista como um guia pra não cair nessas armadilhas. Lembra: foreign key é seu parceiro, não inimigo. O segredo é usar do jeito certo, aí seu banco vai ser base forte pro projeto durar muito tempo.
GO TO FULL VERSION