Chave Primária e Chave Estrangeira em SQLite com exemplos

⚡ Resumo Inteligente

Chaves primárias e chaves estrangeiras em SQLite Garantir a integridade dos dados é feito identificando exclusivamente cada linha e vinculando tabelas relacionadas, assegurando que os valores referenciados sempre existam e evitando registros duplicados, nulos ou órfãos em um banco de dados relacional.

  • 🔑 Chave primária: Uma chave primária identifica cada linha de forma única, e seus valores devem ser únicos e nunca nulos.
  • 🧩 Chave Composta: A combinação de duas ou mais colunas forma uma chave primária composta quando nenhuma coluna individual é única.
  • 🔗 Chave Estrangeira: Uma chave estrangeira faz referência a uma chave da tabela pai e garante a integridade referencial entre tabelas relacionadas.
  • ⚙️ Ativar a aplicação da lei: SQLite Por padrão, as chaves estrangeiras são desativadas; portanto, execute PRAGMA foreign_keys = ON para ativá-las.
  • 🧱 Restrições de coluna: As regras NOT NULL, DEFAULT, UNIQUE e CHECK validam os valores antes de serem inseridos em uma coluna.
  • 🤖 Assistência de IA: Assistentes de IA de texto para SQL e o GitHub Copilot geram SQL de chave e restrição a partir de texto em inglês simples.

Chave Primária e Chave Estrangeira em SQLite

As seções abaixo explicam SQLite As restrições são detalhadas, começando pela PRIMARY KEY e FOREIGN KEY que definem e conectam as tabelas, e abrangendo as regras NOT NULL, DEFAULT, UNIQUE e CHECK que validam os dados em cada coluna.

SQLite restrições

As restrições de coluna impõem regras aos valores inseridos em uma coluna para validar os dados. Essas restrições são definidas na criação de uma tabela, dentro da definição da coluna. Elas mantêm os dados armazenados consistentes e precisos, rejeitando valores que violam as regras definidas, como duplicados, nulos ou valores que não existem em uma tabela relacionada.

SQLite Chave primária

Todos os valores em uma coluna de chave primária devem ser únicos e não nulos. A chave primária identifica exclusivamente cada linha da tabela.

A chave primária pode ser aplicada a apenas uma coluna ou a uma combinação de colunas. Neste último caso, a combinação dos valores das colunas deve ser única para todas as linhas da tabela.

Sintaxe:

Existem diversas maneiras diferentes de definir uma chave primária em uma tabela:

Na própria definição da coluna:

ColumnName INTEGER NOT NULL PRIMARY KEY;

Como uma definição separada:

PRIMARY KEY(ColumnName);

Para criar uma combinação de colunas como chave primária:

PRIMARY KEY(ColumnName1, ColumnName2);

SQLite Restrições NOT NULL, DEFAULT, UNIQUE e CHECK

Além da chave primária, SQLite Fornece diversas restrições de coluna que validam os valores inseridos em uma tabela. As restrições NOT NULL, DEFAULT, UNIQUE e CHECK são definidas na definição da coluna e cada uma delas impõe uma regra específica à coluna. tipo de dados e valores.

Restrição NOT NULL

O SQLite A restrição NOT NULL impede que uma coluna tenha um valor nulo:

ColumnName INTEGER  NOT NULL;

Restrição DEFAULT

Com o SQLite Restrição DEFAULT: se você não inserir nenhum valor em uma coluna, o valor padrão será inserido em seu lugar.

Por exemplo:

ColumnName INTEGER DEFAULT 0;

Se você escrever uma instrução INSERT e não especificar nenhum valor para essa coluna, a coluna terá o valor 0.

Restrição ÚNICA

O SQLite A restrição UNIQUE impede valores duplicados entre todos os valores da coluna.

Por exemplo:

EmployeeId INTEGER NOT NULL UNIQUE;

Isso garante que o valor de “EmployeeId” seja único; valores duplicados não são permitidos. Observe que isso se aplica somente aos valores da coluna “EmployeeId”.

VERIFICAÇÃO da restrição

O SQLite A restrição CHECK define uma condição para verificar um valor inserido. Se o valor não corresponder à condição, ele não será inserido.

Quantity INTEGER NOT NULL CHECK(Quantity > 10);

Não é possível inserir um valor inferior a 10 na coluna “Quantidade”.

SQLite chave estrangeira

O SQLite Uma chave estrangeira é uma restrição que verifica a existência de um valor presente em uma tabela em outra tabela que possui uma relação com a primeira tabela onde a chave estrangeira está definida.

Ao trabalhar com várias tabelas, existem casos em que duas tabelas se relacionam entre si por meio de uma coluna em comum. Se você deseja garantir que o valor inserido em uma delas exista na coluna da outra tabela, deve usar uma restrição de chave estrangeira na coluna em comum.

Nesse caso, ao tentar inserir um valor nessa coluna, a chave estrangeira garantirá que o valor inserido exista na coluna da tabela referenciada.

Observe que as restrições de chave estrangeira não estão habilitadas por padrão em SQLitePrimeiro, você precisa habilitá-los executando o seguinte comando:

PRAGMA foreign_keys = ON;

Restrições de chave estrangeira foram introduzidas em SQLite a partir da versão 3.6.19.

Exemplo de SQLite chave estrangeira

Suponha que temos duas tabelas: Alunos e Departamentos.

A tabela Alunos contém uma lista de alunos, e a tabela Departamentos contém uma lista dos departamentos. Cada aluno pertence a um departamento; ou seja, cada aluno possui uma coluna departmentId.

Agora veremos como a restrição de chave estrangeira pode ser útil para garantir que o valor do ID do departamento na tabela Alunos exista na tabela Departamentos.

Portanto, se criarmos uma restrição de chave estrangeira no DepartmentId da tabela Students, cada departmentId inserido deverá estar presente na tabela Departments.

CREATE TABLE [Departments] (
	[DepartmentId] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,
	[DepartmentName] NVARCHAR(50)  NULL
);
CREATE TABLE [Students] (
	[StudentId] INTEGER  PRIMARY KEY AUTOINCREMENT NOT NULL,
	[StudentName] NVARCHAR(50)  NULL,
	[DepartmentId] INTEGER  NOT NULL,
	[DateOfBirth] DATE  NULL,
	FOREIGN KEY(DepartmentId) REFERENCES Departments(DepartmentId)
);

Para verificar como as restrições de chave estrangeira podem impedir que um elemento ou valor indefinido seja inserido em uma tabela que tenha relação com outra tabela, analisaremos o seguinte exemplo.

Neste exemplo, a tabela Departamentos possui uma relação de chave estrangeira com a tabela Alunos, portanto, qualquer valor de departmentId inserido na tabela Alunos deve existir na tabela Departamentos. Se você tentar inserir um valor de departmentId que não existe na tabela Departamentos, a restrição de chave estrangeira impedirá a operação.

Vamos inserir dois departamentos, “TI” e “Artes”, na tabela Departamentos com os seguintes dados: Consultas INSERT:

INSERT INTO Departments VALUES(1, 'IT');
INSERT INTO Departments VALUES(2, 'Arts');

As duas instruções devem inserir dois departamentos na tabela Departments. Você pode confirmar se os dois valores foram inseridos executando a consulta “SELECT * FROM Departments” posteriormente:

Resultado da consulta SELECT mostrando os departamentos de TI e Artes em SQLite

Em seguida, tente inserir um novo aluno com um departmentId que não exista na tabela Departments:

INSERT INTO Students(StudentName,DepartmentId) VALUES('John', 5);

A linha não será inserida e você receberá um erro dizendo: Falha na restrição de chave estrangeira.

SQLite Mensagem de erro: falha na restrição de chave estrangeira

Diferença entre chave primária e chave estrangeira em SQLite

As chaves primárias e as chaves estrangeiras ajudam a manter a integridade dos dados, mas desempenham funções diferentes. Uma chave primária identifica linhas dentro de uma única tabela, enquanto uma chave estrangeira vincula linhas entre duas tabelas relacionadas. A tabela abaixo resume as principais diferenças.

Base Chave primária chave estrangeira
Propósito Identifica exclusivamente cada linha em sua respectiva tabela. Refere-se à chave primária de outra tabela para vinculá-las.
Singularidade Os valores devem ser únicos. Os valores podem se repetir, portanto, várias linhas filhas podem compartilhar um mesmo pai.
Valores nulos Não pode ser nulo Pode ser nulo quando o relacionamento for opcional.
Número por mesa Apenas uma chave primária por tabela. Uma tabela pode ter várias chaves estrangeiras.
Indexação Indexado automaticamente Não indexado automaticamente; adicione um para melhorar o desempenho.

No exemplo de Alunos e Departamentos, DepartmentId é a chave primária da tabela Departamentos e uma chave estrangeira na tabela Alunos, que vincula cada aluno a um departamento válido.

SQLite Chave primária composta

Uma chave primária composta é uma chave primária formada por duas ou mais colunas. Ela é utilizada quando nenhuma coluna individualmente é única, mas a combinação das colunas é única para cada linha. SQLite Trata os valores combinados como uma única chave.

Por exemplo, uma tabela de matrículas pode permitir que o mesmo aluno esteja em vários cursos e que o mesmo curso seja frequentado por vários alunos, mas cada par aluno-curso deve aparecer apenas uma vez:

CREATE TABLE Enrollments (
	StudentId INTEGER NOT NULL,
	CourseId INTEGER NOT NULL,
	Grade TEXT,
	PRIMARY KEY (StudentId, CourseId)
);

Neste caso, nem o StudentId nem o CourseId são únicos individualmente, mas o par (StudentId, CourseId) é único, portanto o mesmo aluno não pode estar matriculado no mesmo curso duas vezes. Observe os seguintes pontos ao usar uma chave composta:

  • Utilize uma chave composta quando uma única coluna não for capaz de identificar uma linha de forma exclusiva.
  • Cada coluna na chave composta segue as regras da chave primária, portanto o valor combinado deve ser único e não nulo.
  • Uma chave composta é escrita como uma cláusula PRIMARY KEY separada no nível da tabela, e não dentro de uma única definição de coluna.

SQLite Ações de chave estrangeira: AO EXCLUIR e AO ATUALIZAR

Uma chave estrangeira também pode controlar o que acontece com as linhas filhas quando a linha pai à qual elas fazem referência é excluída ou atualizada. Essas ações referenciais são adicionadas com as cláusulas ON DELETE e ON UPDATE ao definir a chave estrangeira. SQLite Apoia cinco ações:

  • NENHUMA AÇÃO — a ação padrão, que gera um erro se as linhas filhas ainda fizerem referência ao pai.
  • RESTRINGIR — impede a exclusão ou atualização imediata, antes que qualquer outra alteração seja executada.
  • DEFINIR NULO — define a coluna de chave estrangeira filha como nula.
  • CONJUNTO PADRÃO — define a coluna de chave estrangeira filha com seu valor padrão declarado.
  • CASCATA — aplica a mesma alteração às linhas filhas, portanto, excluir um elemento pai exclui seus filhos.

O exemplo abaixo recria a tabela de Alunos para que a exclusão de um departamento exclua automaticamente seus alunos, e a atualização do ID de um departamento atualize os alunos correspondentes:

CREATE TABLE Students (
	StudentId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
	StudentName NVARCHAR(50) NULL,
	DepartmentId INTEGER NOT NULL,
	FOREIGN KEY(DepartmentId) REFERENCES Departments(DepartmentId)
		ON DELETE CASCADE
		ON UPDATE CASCADE
);

Lembre-se de que as ações referenciais só são executadas quando o suporte a chaves estrangeiras está ativado; portanto, execute PRAGMA foreign_keys = ON no início de cada conexão. Sem isso, SQLite Analisa as cláusulas ON DELETE e ON UPDATE, mas não as aplica.

Perguntas Frequentes

Sim. Quando uma única coluna é declarada exatamente como INTEGER PRIMARY KEY, ela se torna um alias para o rowid interno da tabela. SQLite Não mantém um índice separado para ela, portanto as buscas por essa chave são rápidas e não usam armazenamento extra.

A imposição de chaves estrangeiras permanece desativada por padrão para preservar a compatibilidade com versões anteriores de bancos de dados e scripts escritos antes da versão 3.6.19. Cada conexão com o banco de dados deve executar o comando `PRAGMA foreign_keys = ON` antes de prosseguir. SQLite Inicia a verificação das restrições de chave estrangeira.

SQLite O sistema indexa automaticamente chaves primárias e colunas UNIQUE, mas não indexa colunas de chave estrangeira. Como a coluna filha é lida em cada verificação de restrição, recomenda-se criar um índice próprio para cada coluna de chave estrangeira, visando melhor desempenho.

Não. ALTER TABLE em SQLite Não é possível adicionar uma chave primária ou estrangeira a uma tabela existente. Você renomeia a tabela antiga, cria uma nova tabela com a chave definida, copia as linhas com INSERT SELECT e, em seguida, exclui a tabela antiga.

Uma chave primária do tipo INTEGER simples atribui o próximo ID como sendo um acima do maior rowid existente e pode reutilizar IDs após exclusões. AUTOINCREMENTO tracks é o ID mais alto já usado em sqlite_sequence e nunca reutiliza um valor, com um pequeno custo de desempenho.

Esse erro ocorre quando você insere ou atualiza uma linha filha cujo valor de chave estrangeira não possui uma linha correspondente na tabela pai, ou quando você exclui uma linha pai que ainda possui linhas filhas. Insira o registro pai primeiro.

Sim. Assistentes de IA para conversão de texto em SQL transformam uma descrição em linguagem natural das suas tabelas em instruções CREATE TABLE com cláusulas PRIMARY KEY e FOREIGN KEY. Fornecer o esquema existente melhora a precisão, e o SQL gerado deve sempre ser revisado antes de ser executado em dados reais.

Sim. Travas deslizantes portáteis Copiloto do GitHub Sugere-se que o código CREATE TABLE com PRIMARY KEY, FOREIGN KEY e outras restrições sejam inseridos diretamente em editores como... VS CodeEle lê seu esquema e migrações existentes, portanto, suas sugestões reutilizam os nomes reais de suas tabelas e colunas.

Resuma esta postagem com: