Primary Key e Foreign Key – Parte I 

Eae pessoal, hoje vou comentar sobre uma das coisas mais importantes na hora de se criar uma tabela em qualquer banco de dados.

O que é Primary key?

Primary key ou chave primária, em resumo é um índice da sua tabela no qual o valor de seu conteúdo é : único, estático (não deve ser alterada) e JAMAIS será nulo.

Exemplo de Primary Key

Vamos utilizar duas analogias, pois inicialmente é de difícil a compreensão e é um assunto de extrema importância para performance.

Como a própria palavra contém chave vamos pensar o seguinte :

Em uma fábrica de portas, temos uma fabricação em serie da mesma, todas elas possuem o mesmo padrão :  Cor, Altura, Largura, Maçaneta e Fechadura.

Pixar-Theory-Monsters-Inc-Doors

 

Fonte : Inside the magic

Vamos supor que na fábrica foram produzidas 500 portas exatamente iguais, se elas são exatamente iguais, caso eu tenha a chave de uma dessas 500 portas, vou poder entrar em 499 portas?

Para que isto não ocorra, cada maçaneta tem uma chave especifica.

Além do exemplo da fábrica de porta, gostaria de usar outro.

Todos nós como cidadãos brasileiros, possuímos um CPF (Cidadão/Contribuente Pessoa Física), a descrição no site da Receita Federal diz que ele é “único e definitivo” e além disso obrigatório, sendo assim, nós mesmos possuímos uma chave primária : única, definitiva e obrigatória.

Transformando a analogia em código 

Vamos usar a Porta como exemplo, criaremos uma tabela com as colunas descritas acima :  Chave EspecificaCor, Altura, Largura, Maçaneta e Fechadura.

Nosso velho amigo CREATE TABLE nos ajudará com isto, devemos ter algo do gênero:

createTable Porta

Possuímos um tipo DECIMAL  que é utilizado para valores de dados exatos onde não existe arredondamento, pode ser usado para altura, largura, valores monetários, notas, porcentagem e etc. Como criamos um DECIMAL (5,2) , o 5 representa a quantidade de números antes do ponto, e o 2 a quantidade de número após o ponto.

Também existe um tipo novo que não havia comentado, o BIT que você só pode inserir os números 0 ou 1, usado para armazenar valores lógicos e assumindo que 0 é igual a não e 1 é igual a sim.

Inserindo em nossa tabela com Primary Key ou Chave primária

insertTablePorta3

Vamos tentar inserir o mesmo Id na porta mas com informações diferentes para as outras colunas:

insertPkDuplicate

Mas porque deu erro se todas minhas colunas são diferentes ?

Como falei acima, a  primary key deve ser ÚNICA, já tínhamos na nossa ChaveId um valor que tentamos inserir, sendo assim o banco não nos deixa inserir dizendo que estamos violando a propriedade de chave única.

Toda vez que eu criar uma Primary Key vou ter que verificar se o número existe?

O pulo do gato para isso é fazer com que a chave sempre acrescente um número, sendo assim, na criação da tabela:

SQL Server: ChaveId INT IDENTITY(1,1) PRIMARY KEY;

No SQL Server no IDENTITY(1,1) o primeiro 1 significa que quando inserimos pela primeira vez, será atribuído o valor 1 e o segundo valor informa que no novo valor, será somado o valor mais alto com mais um número.

Mas e se eu esqueci de adicionar a opção de IDENTITY?

identity

O ALTER TABLE como o nome sugere, altera a tabela, precisamos colocar o nome da tabela que deve ser alterada, em seguida do nome da coluna com seus tipos.

Inserindo na tabela Porta com Primary Key Identity

insertIdentity

 

Mas porque deu erro ao inserir o campo ChaveId?

Quando falamos que um campo é Identity, o próprio SGBD, Sistema Gerenciador de Banco de Dados irá cuidar deste campo para nós, e não nos deixará inserir, por isso ele retorna um erro quando tentamos inserir em um campo que é Identity.

insertDupIdentity

 

PortaSelect

Boas práticas na criação de Primary Key

Podemos adicionar qualquer tipo como primary Key: INT, VARCHAR, CHAR, DATETIME e etc.

Existe um grande problema em se adicionar  uma coluna do tipo VARCHAR como primary key, pois além de existir uma grande probabilidade deste ser alterado, o que quebra uma das regras de uma primary key de ser estática. Além disso, um VARCHAR pode conter espaços em branco, além de ocuparem mais espaço e a probabilidade de suas consultas ficarem mais lentas é muito alta.

Por isso, como uma boa prática na maioria das vezes usamos o tipo INT, pois ele é estático já que usamos ele como Identity, não pode ser inserido, e muito menos podemos inserir espaços em branco, além de possuir uma cadeia de caracteres de 0 a 10.

Mas e se eu precisar ter um campo do tipo VARCHAR que precise ser único?

Para isto, possuímos o UNIQUE que é uma restrição para garantir que aquela coluna que não é uma primary key não terá valores duplicados.

Adicionando UNIQUE em uma coluna existente:

Comando: ALTER TABLE NomeTabela ADD UNIQUE (NomeColuna);

AlterUnique

A grande vantagem de se usar o UNIQUE é que em uma tabela podemos ter somente uma primary key, porém, podemos ter várias  colunas como UNIQUE.

Composite Primary Key ou Chave primária composta 

Acima falei que uma tabela só pode ter uma Primary Key, o que é uma mentira, pois uma tabela pode ter uma ou mais colunas como primary key. Quando em uma tabela, temos uma Primary Key que é composta por duas ou mais colunas, se denomina como Composite Primary Key ou em português Chave Primária Composta.

Quando usar?

Vamos usar um exemplo, a tabela Pessoa.

Criamos uma tabela Pessoa da seguinte maneira:

createTablePessoa

Na parte 1 não comentarei sobre a EstadoId , mas ja deixo avisado que é uma Foreign Key de uma tabela Estado.

Temos também um campo Rg do tipo VARCHAR, mas porque VARCHAR se o RG usa números? Bom, além de existirem alguns estados que no RG pode conter letras, se o RG começar com um zero e o tipo dele for inteiro, o inteiro vai automaticamente “excluir” pois para inteiros zero a esquerda não faz diferença alguma.

Vamos  inserir os seguintes dados :

insertPessoa

selectPessoa

Bom, nada de errado correto?  

Errado, por mais que não violamos nenhuma regra do SGBD, é impossível existir um RG no mesmo Estado e com o mesmo número.

Então eu posso usar UNIQUE no RG para resolver este problema?

Vamos testar?

erroInserirUnique

Bom, o  RG é definido por estado, logo eu posso possuir um RG de número 12.312.312-3 e em outro Estado uma outra pessoa pode possuir o mesmo  número de RG.

Para isto usamos uma Composite Primary Key ou Chave Primária Composta, assim se eu tiver um RG com o número 12.312.312-3 para o estado de São Paulo e o mesmo número para o estado do Rio de Janeiro será valido, mas jamais o mesmo número de RG para o mesmo Estado.

addCompositePrimaryKey


Na criação da tabela :

createtableComposite

 

Vamos tentar inserir agora dois itens iguais

insertDupCompositeTemos um erro, que nos explica sobre nossa Composite Primary Key, como já temos um número de RG no mesmo Estado, o banco não nos deixa inserir um segundo, pois temos regras sobre essas duas colunas. Inserindo o mesmo número de Rg em um Estado diferente:

insertdupCompositeCorrect Por mais que o RG tenha o mesmo número o Estado não tem, logo não causa erro. Só causaria erro se ambos fossem iguais.

Pessoal, fico por aqui, na parte II iremos fechar o assunto e falaremos sobre Foreign Key, qualquer dúvida ou sugestão podem me enviar via Facebook ou pelo Linkedln.

Nota sobre a imagem utilizada :

Disponível em: http://www.insidethemagic.net/wp-content/uploads/2013/02/Monsters-Inc-doors_610.jpg . Acesso em julho 2015.

 

Aline Haxkar Lavorato

Apaixonada por C# e SQL Server, acha que programar é igual a video-game ou seja perde horas conectada sem ver dia ou noite. Paixões recentes neste mundo de dev : AngularJS , NoSQL, Cordova e Ionic.

Facebook LinkedIn 

Comentários

comentarios