“Qual é a diferença entre uma restrição de chave primária e uma restrição de chave exclusiva?”
Esta é provavelmente a pergunta de entrevista de emprego mais frequente para desenvolvedores de banco de dados. Neste artigo, tentaremos respondê-la.
Vamos começar analisando o que são chaves primárias e exclusivas, bem como suas semelhanças.
Chave primária
Uma chave primária é usada para identificar exclusivamente cada registro na tabela. Cada tabela deve ter pelo menos uma chave primária. Para definir uma chave primária no SQL Server, basta usar as palavras-chave ‘Primary Key’ após o nome da coluna.
Chave exclusiva
Uma coluna com uma restrição de chave exclusiva pode conter apenas valores exclusivos – isso é o resultado da chave exclusiva que proíbe que valores duplicados sejam armazenados dentro de uma coluna.
Para definir uma chave exclusiva, você deve anexar 'Unique' ao nome do campo. Lembre-se de que não é obrigatório ter uma chave exclusiva em uma tabela.
Exemplo de criação de chaves primárias e exclusivas
O script a seguir cria um banco de dados 'Test' que contém uma tabela chamada 'Cars'.
Esta tabela terá uma coluna de chave primária chamada 'ID' e uma coluna de chave exclusiva chamada 'NumberPlate'.
CREATE DATABASE TEST GO USE TEST GO CREATE TABLE Cars ( ID int PRIMARY KEY, Name varchar(255) NOT NULL, NumberPlate varchar(255) UNIQUE, Model int );
Em seguida, vamos adicionar alguns registros fictícios à nossa tabela ‘Cars’. Execute o seguinte script:
INSERT INTO Cars VALUES (1, 'Toyota', 'ABC 123', 199), (2, 'Toyota', 'ABC 345', 207), (3, 'Toyota', 'ABC 758', 205), (4, 'Toyota', 'ABC 741', 306), (5, 'Toyota', 'ABC 356', 124)
Antes de falarmos sobre as diferenças, vamos primeiro ver as semelhanças entre chaves primárias e exclusivas.
Semelhanças entre chaves primárias e exclusivas
- Colunas com chaves primárias ou exclusivas não podem ter valores duplicados.
Vamos tentar adicionar um novo registro com um valor de ID 2 (que já existe) na tabela ‘Cars’. Execute o seguinte script:
INSERT INTO Cars VALUES (2, 'Toyota', 'ABC 345', 356)
Ao executar o script acima, o seguinte erro será exibido:
O erro diz claramente que esta instrução viola a restrição de chave primária e que valores duplicados não podem ser inseridos na coluna de chave primária.
Da mesma forma, vamos tentar inserir um valor duplicado na coluna ‘NumberPlate’ com uma restrição de chave exclusiva usando a seguinte consulta:
INSERT INTO Cars VALUES (6, 'Toyota', 'ABC 345', 356)
Desta vez, você verá que há uma violação da restrição de chave exclusiva, pois o valor 'ABC 345' já existe na coluna 'NumberPlate', que possui uma restrição de chave exclusiva. A mensagem de erro ficará assim:
- Como a chave primária e as colunas exclusivas não aceitam valores duplicados, elas podem ser usadas para identificar exclusivamente um registro na tabela. Isso significa que, para cada valor na coluna de chave primária ou exclusiva, apenas um registro será retornado.
Diferenças entre chaves primárias e exclusivas
Agora que entendemos as semelhanças entre chaves primárias e exclusivas, vamos dar uma olhada em suas diferenças.
- Uma tabela pode ter apenas uma chave primária, mas várias chaves exclusivas.
O exemplo a seguir nos ajudará a entender melhor.
Dentro do banco de dados ‘Test’ que fizemos anteriormente, vamos criar uma nova tabela ‘Cars2’ com duas chaves primárias. Para isso, execute o seguinte script:
CREATE TABLE Cars2 ( ID int PRIMARY KEY, Name varchar(255) NOT NULL, NumberPlate varchar(255) UNIQUE, Model int PRIMARY KEY );
No script acima, definimos restrições de chave primária nas colunas ID e Modelo. No entanto, como apenas uma coluna em uma tabela pode ter uma restrição de chave primária, você verá o seguinte erro:
Essa mensagem de erro nos informa claramente que uma tabela não pode ter várias restrições de chave primária.
Agora, vamos adicionar várias restrições de chave exclusivas à tabela ‘Cars2’. Dê uma olhada no script a seguir:
CREATE TABLE Cars2 ( ID int PRIMARY KEY, Name varchar(255) NOT NULL, NumberPlate varchar(255) UNIQUE, Model int UNIQUE );
Isso nos permite adicionar restrições de chave exclusivas nas colunas 'NumberPlate' e 'Model'. Como uma tabela pode ter várias colunas com restrições de chave exclusivas, você não verá nenhuma mensagem de erro ao executar o script acima.
- A coluna de chave primária não pode ter valores nulos, enquanto a coluna de chave exclusiva pode ter um valor nulo.
Vamos ver isso em ação. Primeiro, vamos adicionar um registro com um valor nulo a uma coluna de chave primária na tabela ‘Cars’. Observe o roteiro abaixo:
INSERT INTO Cars VALUES ( null, 'Toyota', 'ABC 345', 356)
Você pode ver que esse script insere null como um valor na coluna ID. Ao executá-lo, você deverá ver o seguinte erro na janela de mensagem de saída:
O erro nos diz que um valor nulo não pode ser inserido, pois a coluna de chave primária não permite valores nulos.
Vamos agora tentar adicionar valores nulos à coluna de chave exclusiva 'NumberPlate'. Para isso, execute o seguinte script:
INSERT INTO Cars VALUES ( 6, 'Toyota',null, 356)
Isso adiciona um novo registro com um valor de ID de 6 e valor nulo à tabela ‘Carros’ – especificamente, o valor nulo é atribuído à coluna ‘NumberPlate’. Você verá que o script acima será executado sem erros, pois a coluna de chave exclusiva pode aceitar valores nulos por padrão.
Para verificar se o valor nulo foi realmente inserido na coluna ‘NumberPlate’, precisaremos selecionar todos os registros da tabela ‘Cars’ usando o seguinte script:
SELECT * FROM Cars
No conjunto de resultados acima, podemos ver claramente que a coluna de chave primária 'ID' não 'não contém nenhum valor nulo. Por outro lado, a coluna ‘NumberPlate’ com uma restrição de chave exclusiva contém um valor nulo que acabamos de inserir. Lembre-se, você não pode adicionar mais de um valor nulo a uma coluna de chave exclusiva, pois o segundo valor nulo será a duplicata do primeiro – e duplicatas não são permitidas.
- Por padrão, um índice clusterizado exclusivo é criado na coluna de chave primária; por outro lado, um índice exclusivo não clusterizado é criado na coluna de chave exclusiva.
Para ver os índices na tabela ‘Cars’, execute o seguinte script:
USE TEST GO sp_help Cars
Na saída, você verá detalhes da tabela ‘Cars’ incluindo os índices conforme mostrado na figura abaixo:
Na figura acima, você pode ver que a coluna 'NumberPlate' possui um índice exclusivo não clusterizado, enquanto a coluna ID possui um índice exclusivo clusterizado.
Conclusão
Apesar de algumas semelhanças básicas, as chaves primárias e exclusivas têm diferenças significativas. Você só pode ter uma chave primária por tabela, mas várias chaves exclusivas. Da mesma forma, uma coluna de chave primária não aceita valores nulos, enquanto colunas de chave exclusivas podem conter um valor nulo cada. E, finalmente, a coluna de chave primária possui um índice clusterizado exclusivo, enquanto uma coluna de chave exclusiva possui um índice não clusterizado exclusivo.