Aprenda a relacionar tabelas com FOREIGN KEY garantindo integridade referencial. Veja 1‑para‑N, tabelas de junção (N‑para‑N), ações de cascata e como indexar corretamente.
Entender FOREIGN KEY: como declarar, quando usar, impactos em INSERT/UPDATE/DELETE, opções de CASCADE e SET NULL, além de práticas para desempenho e manutenção.
FOREIGN KEY (inline na coluna)O que é / Para que serve: Declarar FK na própria coluna que referencia a PK (ou UNIQUE) da tabela pai.
Sintaxe: Coluna TIPO REFERENCES Pai(ChavePai)
Como funciona: O SQL impede inserir valores na coluna que não existam na tabela pai e impede excluir o pai com filhos (salvo ação configurada).
Implicações & boas práticas: • A coluna referenciada deve ser PK ou UNIQUE. • Garanta tipos compatíveis. • Indexe a FK para acelerar JOINs e deletes do pai.
CREATE TABLE dbo.Clientes (
ClienteID INT PRIMARY KEY,
Nome NVARCHAR(100) NOT NULL
);
CREATE TABLE dbo.Pedidos (
PedidoID INT PRIMARY KEY,
ClienteID INT NOT NULL REFERENCES dbo.Clientes(ClienteID),
CriadoEm DATETIME2(3) NOT NULL DEFAULT(SYSDATETIME())
);
-- Falha: não existe cliente 99
-- INSERT INTO dbo.Pedidos (PedidoID,ClienteID) VALUES (1,99);
FOREIGN KEY (constraint nomeada)O que é / Para que serve: Dar nome à constraint e configurar ação ON DELETE/UPDATE.
Sintaxe: CONSTRAINT FK_Filhos_Pai FOREIGN KEY (ColFilho) REFERENCES Pai(ChavePai) [ON DELETE ...] [ON UPDATE ...]
Como funciona: O nome facilita manutenção. Você pode definir ações ao excluir/atualizar o pai.
Implicações & boas práticas: • Padrões: ON DELETE NO ACTION (bloqueia se houver filhos). • Outras opções: CASCADE e SET NULL.
CREATE TABLE dbo.Pedidos (
PedidoID INT PRIMARY KEY,
ClienteID INT NOT NULL,
CONSTRAINT FK_Pedidos_Clientes
FOREIGN KEY (ClienteID)
REFERENCES dbo.Clientes(ClienteID)
ON DELETE NO ACTION -- padrão
ON UPDATE NO ACTION
);
ON DELETE/UPDATE CASCADEO que é / Para que serve: Propagar exclusão/atualização do pai para os filhos automaticamente.
Sintaxe: FOREIGN KEY (...) REFERENCES Pai(...) ON DELETE CASCADE ON UPDATE CASCADE
Como funciona: Ao excluir o pai, todos os filhos são excluídos; ao atualizar a chave do pai, reflete nos filhos.
Implicações & boas práticas: • Use com cuidado: um DELETE no pai pode excluir muitas linhas. • Boa para dados “dependentes” sem vida própria (ex.: itens do pedido).
CREATE TABLE dbo.Pedidos (
PedidoID INT PRIMARY KEY,
ClienteID INT NOT NULL,
CONSTRAINT FK_Pedidos_Clientes
FOREIGN KEY (ClienteID)
REFERENCES dbo.Clientes(ClienteID)
ON DELETE CASCADE
);
-- Excluir cliente apaga seus pedidos
-- DELETE FROM dbo.Clientes WHERE ClienteID = 1;
ON DELETE SET NULLO que é / Para que serve: Quando o pai é excluído, a FK do filho vira NULL (se permitido).
Sintaxe: FOREIGN KEY (...) REFERENCES Pai(...) ON DELETE SET NULL
Como funciona: Preserva o registro do filho, mas sem vínculo com o pai (FK deve aceitar NULL).
Implicações & boas práticas: • Bom quando o filho pode sobreviver sem pai. • Cuidado com relatórios que assumem vínculo obrigatório.
CREATE TABLE dbo.Orcamentos (
OrcamentoID INT PRIMARY KEY,
ClienteID INT NULL,
CONSTRAINT FK_Orcamentos_Clientes
FOREIGN KEY (ClienteID)
REFERENCES dbo.Clientes(ClienteID)
ON DELETE SET NULL
);
N‑para‑N (tabela de junção)O que é / Para que serve: Relacionamento muitos‑para‑muitos via tabela auxiliar com duas FKs.
Sintaxe: CREATE TABLE Junção (AId INT, BId INT, PRIMARY KEY(AId,BId), FK→A, FK→B)
Como funciona: A tabela de junção guarda os pares; a PK composta evita duplicatas.
Implicações & boas práticas: • Indexe as duas colunas. • Considere ON DELETE CASCADE para limpar pares automaticamente.
CREATE TABLE dbo.Alunos (
AlunoID INT PRIMARY KEY, Nome NVARCHAR(100) NOT NULL
);
CREATE TABLE dbo.Cursos (
CursoID INT PRIMARY KEY, Titulo NVARCHAR(100) NOT NULL
);
CREATE TABLE dbo.AlunoCurso (
AlunoID INT NOT NULL,
CursoID INT NOT NULL,
CONSTRAINT PK_AlunoCurso PRIMARY KEY (AlunoID, CursoID),
CONSTRAINT FK_AlunoCurso_Alunos FOREIGN KEY (AlunoID) REFERENCES dbo.Alunos(AlunoID) ON DELETE CASCADE,
CONSTRAINT FK_AlunoCurso_Cursos FOREIGN KEY (CursoID) REFERENCES dbo.Cursos(CursoID) ON DELETE CASCADE
);
Crie índice na coluna filha da FK para acelerar JOINs e exclusões do pai.
CREATE INDEX IX_Pedidos_ClienteID ON dbo.Pedidos(ClienteID);
Você pode desabilitar a checagem temporariamente (não recomendado em produção), inserir/migrar e reabilitar verificando todos os dados.
-- Desabilitar verificação (aceita dados possivelmente inválidos)
ALTER TABLE dbo.Pedidos NOCHECK CONSTRAINT FK_Pedidos_Clientes;
GO
-- Reabilitar e checar todas as linhas (recomendado)
ALTER TABLE dbo.Pedidos WITH CHECK CHECK CONSTRAINT FK_Pedidos_Clientes;
INT vs BIGINT) — alinhe os tipos.