Do not speak Portuguese? Translate this site with Google or Bing Translator
CHAVE PRIMÁRIA SIMPLES E CHAVE PRIMÁRIA COMPOSTA

Posted on: December 03, 2021 12:15 PM

Posted by: Renato

Categories: sql dba database

Views: 13121

CHAVE PRIMÁRIA SIMPLES E CHAVE PRIMÁRIA COMPOSTA

É possível criar duas chaves primárias em uma mesma tabela ou o conceito correto seria criar uma chave primária composta? Entenda a diferença e algumas respostas para dúvidas relacionadas a chave primária e sua finalidade em uma tabela do banco de dados.

Uma das características mais importantes da modelagem de dados é compreender o conceito de chave primária. A chave primária é usada para criar um mecanismo de controle que permite com que os dados inseridos em uma tabela do banco de dados sejam consistentes, isto é, que não haja dados duplicados.

Chave primária simples

O exemplo abaixo mostra como criar uma tabela com uma chave primária simples. Perceba que a chave primária foi criada no campo cidade.

 

create table cidades(cidade varchar(100) primary key,estado varchar(10),populacao int)

 

Agora considere o exemplo abaixo que irá inserir os dados das cidades de Rio Claro/SP e Rio Claro/RJ na tabela criada.

 

insert into cidades values('Rio Claro','SP',185421)

 

insert into cidades values('Rio Claro','RJ',17216)

 

No exemplo acima teremos um erro, pois há uma violação da chave primária, já que o nome Rio Claro será duplicado e isto não é permitido.

Chave primária composta

A solução para o problema acima é criarmos uma chave primária composta. É muito importante entendermos que não existe duas chaves primárias e sim chave primária composta.

A chave primária composta é aquela que é criada em dois campos e desta forma passa a utilizar a junção dos dados dos dois campos indicados para formar um valor único e assim aplicar o bloqueio de duplicidade.

No nosso exemplo, poderemos usar o campo estado junto com o campo cidade para formar uma chave composta. Desta forma Rio Claro/SP será diferente de Rio claro/RJ. Veja o exemplo abaixo:

 

create table cidades(

 

cidade varchar(100),

estado varchar(10),

populacao int,

CONSTRAINT pk_CE primary key(cidade,estado)

)

 

Constraint é o mesmo que restrição, já que a chave primária é uma restrição. pk_CE é o nome da restrição. Cidade e  estado são os campos que usei para criar a chave composta.

Se executarmos novamente o exemplo do insert, como mostrado abaixo, não teremos erro já que a junção dos nomes das cidades com o estado gerou termos diferentes.

 

insert into cidades values('Rio Claro','SP',185421)

 

insert into cidades values('Rio Claro','RJ',17216)

 

Simples não?

Alguém poderia perguntar: Não seria melhor criar um campo de código da cidade e usá-lo como chave primária simples? Sim. Quando isso for possível, creio que seria mesmo melhor, mas nem sempre é. Outro ponto importante é que muitos bancos já estão constituídos e outros são objetos de sistemas legados. Enfim, há casos e casos.

Chaves candidatas

Em uma tabela, dependendo da modelagem de dados e das características da mesma, pode existir campos que por sua própria existência já configura um candidato a chave primária, como é o caso dos campos CPF, RG, Nº do título de eleitor, entre outros. Isto acontece porque esses atributos não podem por padrão ter valores repetidos.

Em outros casos há tabelas em que não existe um campo candidato a chave primária e ei devemos criar um campo, ainda que a única finalidade dele seja de exercer o papel de identificação dos registros no banco.

Definição

Uma chave primária é uma restrição que criamos em cima de um ou mais campos de uma tabela no banco de dados para permitir que apenas dados sem repetição sejam inseridos nela. Esta característica que é gerenciada pelo próprio banco ajuda a garantir a integridade dos dados.

Por que preciso usar uma chave primária?

Seja ela simples ou composta, sua utilidade e necessidade é grande em uma tabela do banco. Veja abaixo alguns porquês:

  • Identificação única: A função principal de uma chave primária é tornar um registro de uma tabela único, ou seja, sua finalidade está relacionada com a integridade dos dados. com uso da chave primária podemos garantir que um dado será único, evitando assim a repetição de um dado que poderia causar grande problema na identificação gerando por exemplo informações dúbias. Imagine um sistema de cadastro que permitisse que um CPF fosse cadastrado duas vezes? Consegue imaginar os problemas que isso poderia gerar?
  • Integridade: Diversas operações, como aquelas que envolvem alteração ou exclusão de dados necessitam de uma identificação para serem realizadas. Ao excluir um dado é preciso dizer ao banco quais registros serão afetados. Se a ideia é excluir um grupo de registros não há necessidade de usar uma chave primária, mas se você precisa excluir um registro específico é necessário ter um campo que o identifica de forma a diferenciá-lo dos demais e isto precisa ser feito com absoluta certeza. Nesta hora entra a chave primária.
  • Relacionamento: Outra razão pelo qual devemos criar e usar chaves primárias é que o modelo de banco de dados relacional exige isso. Por relacional devemos entender que há vários objetos (tabelas) e que os mesmos estão relacionados entre si. Para garantir que esse relacionamento seja íntegro usamos chave primária e chave estrangeira que liga um campo da tabela A (chave primária) com um campo da tabela B (chave estrangeira).

 

Posso criar uma tabela sem chave primária?

Sim isso é possível, mas não é o ideal na maioria dos casos. Se você está criando uma tabela que não fará relacionamento com nenhuma outra tabela, na verdade não precisará necessariamente ter uma chave primária, exceto se precisar garantir que os dados sejam únicos. Mas a chave primária está mais relacionada a situações onde você tem múltiplas tabelas e elas serão relacionadas entre si.

Qual a diferença de chave primária e auto numeração?

Auto numeração é um recurso do banco de dados que permite que um campo tenha o seu valor gerado automaticamente e de forma sequencial, não necessitando assim informar o valor para ele. Imagine que você tenha um cadastro e queira numerar sequencialmente os registros, para isso poderia criar um campo ID ou código e setar para ser auto-increment (mySQL) ou identity (SQL Server), por exemplo.

A chave primária pode ser aplicada inclusive nesse mesmo campo, mas a sua função é de garantir a integridade, dados únicos e permitir relacionamento, Mas ela não implica na geração de valores automático para um campo, seja ele qual for.

|--------------------------------------------------------------------------------------------------------------------|

7 motivos para não usar chaves compostas

Peguei pesado no título certo? Foi de propósito. É daqueles títulos para gerar emoções mesmo. Provavelmente muitos atirarão pedras, mas às vezes precisamos expor nossas ideias, principalmente quando temos algumas convicções. Mas serei bastante racional e apoiarei minhas considerações em autores consagrados como Eric Evans, Martin Fowler, além de vivências próprias.

Provavelmente você conheça pessoas que defendam chaves primárias simples, e outras pessoas que defendam chaves primárias compostas com unhas e dentes. Neste artigo, vou tentar apresentar argumentos técnicos pelos quais eu acredito que o uso de chaves primárias simples facilita o desenvolvimento e a manutenção de sistemas complexos.

Para começar, vamos imaginar um cenário (parcial). Um sistema acadêmico, onde temos o conceito de aluno, contrato, turma, matrícula, curso, disciplina, e outros. Um aluno pode ter um contrato, que por sua vez vincula o aluno a um curso. Vamos supor que existe uma regra de negócio, que diz que um aluno só pode ter um contrato com cada curso. Assim, se ele sai do curso e volta para o curso, estamos falando do mesmo contrato que é reativado. O contrato vincula então o aluno a um curso e possui matrículas, que são registros que vinculam aquele contrato às turmas. Uma matrícula é o registro daquele aluno (que é representado pelo contrato) em uma turma. A matrícula não está diretamente vinculada à pessoa, pois para a montagem do histórico escolar é preciso saber de qual curso (contrato) ela se refere. A matrícula está vinculada a uma turma, que representa a ocorrência de uma disciplina dentro de um semestre.

Obviamente o sistema está incompleto, faltam muitos atributos, relações e outros. Por exemplo, teríamos que vincular as disciplinas aos cursos (N-N), mas isso não colabora para o entendimento dos propósitos deste artigo. Então vamos simplificar as coisas.

Modelo de referência usando chaves simples

Primeiro vamos ver como seria o modelo usando chaves primárias simples. Veja que cada tabela necessariamente possui um ID para identificar uma linha de registro naquela tabela. Então sempre que precisarmos realizar uma operação sobre uma matrícula, por exemplo, bastaria sabermos o ID do registro. A relação para o contrato é realizada por uma chave estrangeira simples, bem como para a turma. Podemos ainda criar um índice único (unique index) para as chaves estrangeiras, para fazer que o próprio banco impeça a inserção de combinações repetidas de registros (contrato+turma).

Modelo com chaves primárias simples

Modelo com chaves primárias simples

O que não escolher como chave primária

Ao modelarmos as classes de um sistema, algumas delas são Entities, outras Value Objects, algumas Aggretates. Para Evans, Um objeto do tipo ENTITY é um objeto que possui uma identidade única, que dura em seu ciclo de vida. Uma pessoa, por exemplo, seus atributos podem mudar, mas sua identidade permanece. Uma ENTITY pode ser uma pessoa, um contrato, uma matrícula, etc.

Uma ENTITY pode ser transmitida por um Web Service, armazenada e obtida do Banco de dados múltiplas vezes. Em cada processo, um novo objeto é instanciado na memória. O que mantém a identidade é um atributo único e imutável, que pode ser garantido também em banco de dados.

Muitas pessoas são tentadas a usar atributos do mundo real como chave de um objeto. Identificar uma pessoa pelo CPF, uma empresa pelo CNPJ, um livro pelo ISBN são alguns exemplos. Mas por que evitar essas estratégias que utilizam atributos do mundo real para identificar objetos?

Um objeto deve ser identificado de maneira única e imutável. Caso contrário, o que seria de seu banco de dados se as chaves ficassem mudando a toda hora? Impensável. Mas por que campos como CPF e CNPJ mudariam? Eu explico… Eles representam uma pessoa (física ou jurídica) perante nosso sistema de registros do Brasil, e não identificam unicamente aquela pessoa no universo. Assim sendo, o Brasil pode mudar seu sistema de registros e codificações, mudando também os valores dessas chaves, e até seus nomes. Assim, sua base de dados ficaria suscetível a essas mudanças. Imagine você tendo que dar UPDATE em várias tabelas que referenciavam o CPF da pessoa, que nem se chama mais CPF, e agora possui uma outra estrutura e formato.

Então para evitar esses problemas, lembre-se de que uma chave deve ser única e imutável. Para garantir essas condições e vincular os registros da base de dados de maneira que a estrutura não precise passar por mudanças futuras devido à mudanças na maneira como o mundo real identifica aquele objeto, utilize chaves artificiais (surrogate), geradas pelo próprio banco (autoincrement), numéricas. Assim, você garantirá que estas não sofrerão mudanças, o que trará maior estabilidade para a estrutura (relações de chave primária e chave estrangeira).

O amigo Elton Minetto acrescenta ainda que “uma grande tendência é a utilização de UUIDs para campos de chave, evitando usar os auto_increment dos bancos de dados”. Para ele, UUIDs “ajudam a migrar de banco ou mesmo ter bancos distribuídos em algum momento do projeto”. O amigo Renato Mendes Figueiredo complementa ainda que UUIDs “aliviam a carga do banco de gerar ids e fazem com que a aplicação não se preocupe com ordem ou unicidade”.

Modelo de referência usando chaves compostas

Mesmo que você persista na ideia de usar chaves primárias compostas, nessa versão do modelo, teríamos algumas mudanças. As tabelas mais simples (pessoa, disciplina, curso) continuariam da mesma forma, pois elas somente possuem um atributo para identificação, de qualquer maneira. A coisa começa a mudar para contratos. Como um contrato é único pela combinação pessoa+curso, ele teria uma chave primária composta por id_pessoa e id_curso. Assim, sempre que quisermos realizar alguma operação sobre o contrato, precisaríamos informar as duas chaves. O mesmo ocorre com a matrícula, que antes tinha a chave do contrato e da turma. Como a chave do contrato é composta, agora ela é representada por uma chave composta tripla (pessoa, curso, e turma), para evitar que essa combinação se repita. E sempre que quisermos realizar alguma operação sobre um registro de matrícula (select, update), todas chaves deverão ser informadas.

Modelo com chaves compostas

Modelo com chaves compostas

Agora voltamos para a motivação original deste artigo. Motivar o leitor a construir sistemas com o uso de chaves primárias simples, não compostas. Procuramos organizar os motivos em tópicos para facilitar a discussão, e também a visualização das razões.

1. A persistência é muito mais simples

Um Design Pattern consagrado para implementar a persistência de uma ENTITY é um ACTIVE RECORD. Para Fowler, Um ACTIVE RECORD é “Um objeto que representa uma linha de uma tabela, e encapsula o acesso aos dados e adiciona lógica de domínio”. ACTIVE RECORD é possivelmente o padrão de projetos mais utilizado em camadas de persistência por sua facilidade de uso. A seguir, temos um exemplo onde carregamos o objeto Contrato para a memória baseado em seu ID. Pense na facilidade que é o mapeamento entre um registro da base de dados e a memória com um campo único e simples para identificar aquele objeto. Agora imagine o carregamento deste objeto a partir de vários atributos que o identificariam ao trocarmos para chaves compostas. Você pode recorrer a outros padrões como DATA MAPPER, mas aí a brincadeira não é tão divertida, pois cada classe demandaria de um mapper para ela, ou seja, mais código para dar manutenção.


 
  1. <?php
  2. $contrato = Contrato::find($param[‘id’]);
  3. $contrato->dt_desativacao = date(‘Y-m-d’);
  4. $contrato->save();
  5. ?>

Uma das premissas para utilização do ACTIVE RECORD é outro padrão chamado IDENTITY FIELD. Para Fowler, um IDENTITY FIELD “Salva um campo de ID do banco de dados no objeto para manter a identidade entre o objeto da memória e a linha no banco de dados”.

Enquanto no Banco de dados utilizamos chaves primárias para referenciar registros, na memória, usamos ponteiros (variáveis) para referenciar objetos. Para manter a relação entre Banco de dados e memória, é necessário um campo de identificação que deve ser preservado em memória, para saber que quando for atualizado no banco, trata-se do mesmo registro, não um novo. Geralmente, os mecanismos de persistência se dão muito melhor com chave única, não composta. Lembre-se de usar uma chave sem significado (surrogate), menos suscetível à mudanças do mundo real.

2. Cache de objetos (Identity Map)

Há alguns anos, tínhamos um problema de performance em um cliente, a Universidade Univates. Durante a matrícula haviam cerca de 5 mil alunos fazendo o processo simultaneamente (simultaneamente mesmo), sendo que o processo carregava muitos objetos para a memória para fazer cálculos financeiros, registros de matrículas e mais uma série de regras de negócio. O servidor estava no limite e aumentar o hardware era uma opção existente, porém cara.

Verificamos que alguns objetos (como os de configuração) eram carregados inúmeras vezes durante uma mesma matrícula. Resolvemos criar um cache de objetos em memória RAM usando a tecnologia APC do PHP. Assim, uma vez que o objeto fosse carregado do banco, ele ia para o cache. Em requisições posteriores, buscávamos sempre do cache em primeiro lugar. Apenas uma tabela era consultada 250 vezes nesse processo, visto que era uma tabela chave/valor usada para buscar diferentes parâmetros de configuração). Mas aplicamos esta técnica também para tabelas de cursos, de cidades, de pessoas. Esta técnica poupou milhares de consultas no banco por processo de matrícula, e milhões de consultas ao longo de um mês. Não foi necessário fazer upgrade de hardware, e o processo ficou muito mais fluido, visto que o tempo de consulta no cache era ínfimo perto do tempo de consulta no banco de dados relacional.

Esta técnica é descrita por Fowler no Design Pattern IDENTITY MAP. Para Fowler, um IDENTITY MAP, “Garante que cada objeto é carregado apenas uma vez, armazenando-o em um mapa. Procura pelos objetos no mapa quando necessário referenciá-los”.

O buscador do IDENTITY MAP, busca no mapa, geralmente pela PK (surrogate). Poupa recursos, carrega somente uma versão do objeto por transação. Quando vai carregar do BD, primeiro verifica o mapa. Se não está no mapa, coloca no mapa.


 
  1. // Abre transação
  2. Curso::find($curso_do_aluno); // se não está no cache, carrega e põe no cache
  3. Curso::find($curso_do_aluno); // carrega do cache
  4. Curso::find($curso_do_aluno); // carrega do cache
  5. // Fecha transação

Você perguntaria, por que cargas d’água, alguém carregaria o mesmo objeto, várias vezes? Perceba que não estamos falando de um mesmo método, mas métodos de diferentes classes, executados dentro da mesma transação. Métodos que carregam um objeto que já tenha sido carregado anteriormente, na mesma transação, ou até mesmo por outro usuário em outra transação.

Imagine um programa de matrículas onde precisaremos do objeto Curso em diversos lugares, como em registros acadêmicos, registros financeiros. Este objeto Curso seria carregado N vezes para apenas 1 aluno durante o processo de matrícula. Ao utilizarmos cache, este objeto não seria mais carregado da base de dados, e sim do cache, por todos alunos que se matricularem naquele curso. Além disso, funcionários administrativos, ao realizarem operações de retaguarda (relatórios, operações de registro acadêmico) também utilizariam a versão cacheada do registro, tornando todo o sistema mais rápido e fluido.

Ferramentas de cache, como o APC, o Redis, operam geralmente no padrão chave-valor. Agora imagine a complexidade da implementação de cache com chaves compostas? Veja que neste tipo de implementação (chave simples), a própria chave primária simples identifica o objeto no cache.

Referências:
http://www.adianti.com.br/forum/pt/view_1341?banco-de-dados-em-memoria-nao-cache-de-objetos

3. Manutenção de cadastros

Formulários

Agora imagine operações básicas no dia a dia como o formulário de cadastro de um objeto. Ao trabalharmos com chaves primárias simples fica muito simples decidir se realizaremos um INSERT ou UPDATE na ação de salvar do formulário. Imagine que estamos cadastrando um contrato novo. Se o objeto possui um ID, executamos um UPDATE, caso contrário, executamos um INSERT na base de dados. O INSERT em um campo de chave primária serial/sequência é mais simples, pois basta não informarmos este campo que o banco usa o auto increment (Ex: PostgreSQL). Mas com chaves compostas, antes precisamos consultar o banco de dados com um critério combinado (Ex: id_pessoa + id_curso) para verificar se aquele registro existe antes da gravação.


 
  1. if (empty( $object->id ))
  2. {
  3. insert...
  4. }
  5. else
  6. {
  7. update...
  8. }

Datagrids

Agora imagine uma datagrid com listagem de contratos. Você tem uma datagrid com ações (Ex: cancelar, reativar, excluir). Ao trabalharmos com chaves primárias simples, basta passar um campo somente pela URL (GET) para identificar o contrato que aplicaremos a ação. Ao trabalharmos com chaves primárias compostas, precisamos passar mais campos pela url (id_aluno + id_curso) para identificar o mesmo registro a ser manipulado. Além disso, o tempo de carregamento com filtro por campo único, em situações normais de temperatura e pressão é menor do que o tempo de carregamento com filtro por mais de um campo (chave composta).

Agora imagine manutenção de registros pelo terminal. Alguém fez alguma coisa errada e você precisa corrigir isso pelo console. Pode ser um UPDATE ou um DELETE, mas sobre alguns registros. Com chaves primárias simples você pode fazer do jeito que está a seguir. Agora imagine como seria dar manutenção nesses registros específicos com chaves primárias compostas.


 
  1. // excluir alguns registros errados
  2. DELETE from contrato where ID IN (5000, 5020, 5030);
  3.  
  4. // corrigir alguns registros
  5. UPDATE matricula set dt_cancelamento=NULL where ID IN (40300, 40301);

Widgets

Agora imagine que você precise fazer uma Combo (SELECT) para listar os contratos de um aluno, para selecionar o contrato sobre o qual fará uma operação. Geralmente esses componentes visuais (Widgets) estão preparados para uma chave (ID) e um valor (Ex: outros campos concatenados). Mas se o contrato possui chave composta, qual será a chave da COMBO? Aí você começará a contornar a situação concatenando os campos, e fazendo um parsing para no outro lado do POST, desmembrar os campos.

4. Proliferação de campos na estrutura

Agora imagine que o aluno não tem mais somente uma nota por matrícula, e sim várias. Então você precisa criar uma tabela que referencia a tabela de matrículas. No modelo de chave primária simples, você precisa adicionar uma única chave estrangeira, e registrar a data e o valor da nota.

Tabela de notas com chaves simples

Tabela de notas com chaves simples

Já no modelo de chave primária composta, você precisa adicionar três chaves estrangeiras, uma vez que são as três que identificam unicamente uma matrícula.

Tabela de notas com chaves compostas

Tabela de notas com chaves compostas

Você percebeu que houve uma proliferação de chaves. Esse cascateamento de chaves só tende a piorar com o tamanho do banco. Mais tabelas, mais chaves, e mais Joins em consultas.

5. Consultas com Joins

Agora imagine que você precisa construir relatórios com queries cruzando várias tabelas, pois você precisa pesquisar dados de diferentes lugares. Ao utilizarmos chaves primárias simples, temos ligações mais simples em Joins de queries também. Ao utilizarmos chaves primárias compostas, temos mais campos para lembrar ao fazer as ligações. Devido ao nosso modelo ser minimalista, esta diferença não ficará tanto evidente quanto gostaríamos. Mas a medida em que o sistema se torna maior, as diferenças se tornarão maiores.

Aqui veja que a tabela de matrícula se ligará com contrato por apenas um campo de ligação.


 
  1. SELECT pessoa.nome,
  2. disciplina.nome,
  3. matricula.dt_matricula,
  4. matricula.nota
  5. FROM pessoa, contrato, matricula, turma, disciplina
  6. WHERE pessoa.id = contrato.id_pessoa
  7. AND contrato.id = matricula.id_contrato
  8. AND matricula.id_turma = turma.id
  9. AND turma.id_disciplina = disciplina.id
  10. AND turma.id = 5003;

Aqui veja que é necessário conectarmos cada um dos campos de chave estrangeira.


 
  1. SELECT pessoa.nome,
  2. disciplina.nome,
  3. matricula.dt_matricula,
  4. matricula.nota
  5. FROM pessoa, contrato, matricula, turma, disciplina
  6. WHERE pessoa.id = contrato.id_pessoa
  7. AND contrato.id_pessoa = matricula.id_pessoa
  8. AND contrato.id_curso = matricula.id_curso
  9. AND matricula.id_turma = turma.id
  10. AND turma.id_disciplina = disciplina.id
  11. AND turma.id = 5003;

Em princípio, vimos que serão necessários mais Joins. Mas além disso, no quesito performance, note que mais Joins são necessários para obter o mesmo resultado. Ao utilizarmos chaves primárias simples, os índices acabam sendo mais compactos, o que privilegia as estratégias de busca.

6. Logs de alterações de registros

Hoje em dia é quase impensável construirmos uma boa aplicação de negócio sem logs. Nas nossas aplicações, no mínimo fazemos logs de acesso (login, logout), logs de SQL executados (INSERT, UPDATE), e logs de alteração de registros. Os logs de alteração de registros armazenam o estado de um objeto antes e depois da alteração.

A tabela a seguir apresenta os logs de alteração. Veja que temos uma estrutura bem simples com: chave do registro alterado, data da alteração, login do usuário, tabela, nome da coluna, operação realizada, valor antigo, e valor novo. A estrutura é sempre essa, independente da tabela, e do campo a ser logado.

Para implementar este Log também é bastante simples. Como utilizamos um Active Record, o próprio objeto realiza a comparação com seu estado prévio antes da gravação na base de dados.
Agora, como realizaríamos o registro de logs de registros que possuem chaves compostas? Criar várias colunas para identificação seria inviável, pois o número de colunas que identifica um registro usando chave composta é variável por tabela. Teríamos de novamente contornar a situação fazendo com que a coluna de identificação seja alguma coisa serializada ou concatenada. Caso optássemos por fazer dessa maneira, agora como você localizaria facilmente esses logs depois? Imagine que precisa identificar todas alterações em um contrato específico. Vai pensando…

Logs

Logs

7. REST API

Boa parte das API’s REST são construídas seguindo o padrão apresentado na tabela a seguir, onde o recurso a ser manipulado é identificado única e exclusivamente por um ID simples. Veja que nem ao menos o nome do atributo (ID) identificamos. Agora imagine que precisamos obter os dados de um contrato via API (operação GET por ID). Ao trabalharmos com chave simples, a operação também é simples GET https://dominio/contrato/1.

Método Exemplo Descrição
GET https://dominio/pessoas Lista todas as pessoas
GET https://dominio/pessoa/1 Lista apenas pessoas com id = 1
POST https://dominio/pessoas Para cadastrar pessoas
PUT https://dominio/pessoa/1 Para editar pessoas
DELETE https://dominio/pessoa/1 Para apagar pessoas

Agora imagine como ficaria a chamada com o contrato representado por chaves primárias compostas. Teríamos de definir rotas formadas por vários atributos que identificam o objeto, o que não é a linguagem comum do universo REST. Complicou né? É claro que você vai encontrar uma saída, mas pense bem, ela poderá ser mais um “contorno” em seu projeto. O default todo mundo implementa, o diferente possivelmente gerará mais um trabalho extra, não esperado.

Método Exemplo Descrição
GET https://dominio/contrato/53/87 Contrato do aluno 53, curso 87
GET https://dominio/contrato?aluno=53&curso=87 Contrato do aluno 53, curso 87

A segunda ideia é ruim, pois vincula (acopla) o resource com o schema da base de dados.

O amigo Renato Mendes Figueiredo, acrescenta também que “No caso do restful tem uma desvantagem também, criar todos os resources com um modelo de dados muito segmentado faz com que diversas calls sejam necessárias na API pra criar todo o modelo de dados”.

Considerações finais

Neste artigo procurei apresentar padrões de projeto de dois dos mais respeitáveis Engenheiros de Software do mundo, Eric Evans e Martin Fowler, além de exemplos bem práticos que trabalhamos no dia a dia. Menu objetivo com este artigo é mostrar que o somatório de detalhes podem fazer uma grande diferença. Ao implementarmos um sistema grande, temos que eliminar pequenos obstáculos e facilitar nossa vida, não complicar. É possível utilizarmos tanto a abordagem de chaves primárias simples, quanto compostas. Mas veja que ao escolhermos chaves primárias simples, teremos vários atalhos, facilidades. Essas facilidades se traduzem em ganho de tempo, código mais enxuto, e menos dor de cabeça tentando adaptar técnicas que nasceram para ser simples, não complexas.

Gostaria ainda de agradecer os amigos Renato Mendes Figueiredo e Elton Minetto pela revisão do artigo e contribuições preciosas.

Fonte:

https://dalloglio.net/140?7-motivos-para-nao-usar-chaves-compostas

https://www.luis.blog.br/chave-primaria-simples-e-chave-primaria-composta.html


4

Share

Donate to Site


About Author

Renato

Developer

Add a Comment
Comments 0 Comments

No comments yet! Be the first to comment

Blog Search


Categories

OUTROS (15) Variados (109) PHP (130) Laravel (157) Black Hat (3) front-end (28) linux (113) postgresql (39) Docker (26) rest (5) soap (1) webservice (6) October (1) CMS (2) node (7) backend (13) ubuntu (54) devops (25) nodejs (5) npm (2) nvm (1) git (8) firefox (1) react (6) reactnative (5) collections (1) javascript (6) reactjs (7) yarn (0) adb (1) Solid (2) blade (3) models (1) controllers (0) log (1) html (2) hardware (3) aws (14) Transcribe (2) transcription (1) google (4) ibm (1) nuance (1) PHP Swoole (5) mysql (31) macox (4) flutter (1) symfony (1) cor (1) colors (2) homeOffice (2) jobs (3) imagick (2) ec2 (1) sw (1) websocket (1) markdown (1) ckeditor (1) tecnologia (14) faceapp (1) eloquent (14) query (4) sql (40) ddd (3) nginx (9) apache (4) certbot (1) lets-encrypt (3) debian (11) liquid (1) magento (2) ruby (1) LETSENCRYPT (1) Fibonacci (1) wine (1) transaction (1) pendrive (1) boot (1) usb (1) prf (1) policia (2) federal (1) lucena (1) mongodb (4) paypal (1) payment (1) zend (1) vim (4) ciencia (6) js (1) nosql (1) java (1) JasperReports (1) phpjasper (1) covid19 (1) saude (1) athena (1) cinnamon (1) phpunit (2) binaural (1) mysqli (3) database (42) windows (6) vala (1) json (2) oracle (1) mariadb (4) dev (12) webdev (24) s3 (4) storage (1) kitematic (1) gnome (2) web (2) intel (3) piada (1) cron (2) dba (18) lumen (1) ffmpeg (2) android (2) aplicativo (1) fedora (2) shell (4) bash (3) script (3) lider (1) htm (1) csv (1) dropbox (1) db (3) combustivel (2) haru (1) presenter (1) gasolina (1) MeioAmbiente (1) Grunt (1) biologia (1) programming (22) performance (3) brain (1) smartphones (1) telefonia (1) privacidade (1) opensource (3) microg (1) iode (1) ssh (3) zsh (2) terminal (3) dracula (1) spaceship (1) mac (2) idiomas (1) laptop (2) developer (37) api (4) data (1) matematica (1) seguranca (2) 100DaysOfCode (9) hotfix (1) documentation (1) laravelphp (10) RabbitMQ (1) Elasticsearch (1) redis (2) Raspberry (4) Padrao de design (4) JQuery (1) angularjs (4) Dicas (39) Kubernetes (2) vscode (2) backup (1) angular (3) servers (2) pipelines (1) AppSec (1) DevSecOps (4) rust (1) RustLang (1) Mozilla (1) algoritimo (1) sqlite (1) Passport (1) jwt (4) security (2) translate (1) kube (1) iot (1) politica (2) bolsonaro (1) flow (1) podcast (1) Brasil (1) containers (2) traefik (1) networking (1) host (1) POO (2) microservices (2) bug (1) cqrs (1) arquitetura (2) Architecture (3) sail (3) militar (1) artigo (1) economia (1) forcas armadas (1) ffaa (1) autenticacao (1) autorizacao (2) authentication (4) authorization (2) NoCookies (1) wsl (4) memcached (1) macos (2) unix (2) kali-linux (1) linux-tools (5) apple (1) noticias (2) composer (1) rancher (1) k8s (1) escopos (1) orm (1) jenkins (4) github (5) gitlab (3) queue (1) Passwordless (1) sonarqube (1) phpswoole (1) laraveloctane (1) Swoole (1) Swoole (1) octane (1) Structurizr (1) Diagramas (1) c4 (1) c4-models (1) compactar (1) compression (1) messaging (1) restfull (1) eventdrive (1) services (1) http (1) Monolith (1) microservice (1) historia (1) educacao (1) cavalotroia (1) OOD (0) odd (1) chatgpt (1) openai (3) vicuna (1) llama (1) gpt (1) transformers (1) pytorch (1) tensorflow (1) akitando (1) ia (1) nvidia (1) agi (1) guard (1) multiple_authen (2) rpi (1) auth (1) auth (1) livros (2) ElonMusk (2) Oh My Zsh (1) Manjaro (1) BigLinux (2) ArchLinux (1) Migration (1) Error (1) Monitor (1) Filament (1) LaravelFilament (1) replication (1) phpfpm (1) cache (1) vpn (1) l2tp (1) zorin-os (1) optimization (1) scheduling (1) monitoring (2) linkedin (1) community (1) inteligencia-artificial (2) wsl2 (1) maps (1) API_KEY_GOOGLE_MAPS (1) repmgr (1) altadisponibilidade (1) banco (1) modelagemdedados (1) inteligenciadedados (4) governancadedados (1) bancodedados (2) Observability (1) picpay (1) ecommerce (1)

New Articles



Get Latest Updates by Email